Name

global.SubscriptionDAO

Description

Gets installed as part of com.snc.activity_subscriptions plugin Activity Subscriptions Framework. Contains all the methods to provide Subscription CRUD operations.

Script

var SubscriptionDAO = Class.create();
SubscriptionDAO.prototype = {
  initialize: function(activitySubContext) {
  	this.activitySubContext = activitySubContext;
  	this.Results =  [];
  	this.SUBSCRIPTIONS_TABLE = "sn_actsub_subobject_stream";
  	this.SUB_OBJ_TABLE = "sn_actsub_subscribable_object";
  	this.SUB_OBJ_NOTIF_PREF = "sn_actsub_atype_notif_pref";
  	this.ACTIVITY_USER_STREAM = "sn_actsub_user_stream";
  	this.ACTIVITY_TYPE_PREF = 'sn_actsub_atype_notif_pref';
  	this.SUB_NOTIF_PREF = 'sn_actsub_subscription_notif_pref';
  	this.SUB_META_OBJ_SYS_ID = 'b4e6c9bc530132006242d7b08cc5879c';
  	this.DEFAULT_STREAM = 'Default';
  	this.SUB_OBJ_KB = '722d67c367003200d358bb2d07415a9c';
  	this.SUB_OBJ_KA = '7d8f537453003200fa9bd7b08cc5872c';
  	this.SUB_OBJ_LIVE_PROFILE = '46f9d003db723200624273c8f0b8f54c';
  	this.SUB_OBJ_FORUM = '6cbd03c467103200ace49a6617415ac4';
  	this.SUB_OBJ_TOPIC = '17bd03c467103200ace49a6617415aed';
  	this.SUB_OBJ_IDEA = '62d8370577407300d82ea3334a1061e2';
  	this.MAX_PAGE_SIZE = 15;
  	this.GLOBAL_NOTIF_PREF_ENABLE_VAL = 2;
  	if(this.activitySubContext.isCommunityPluginActive == true){
  		this.enableACL = {};
  		this.enableACL[sn_communities.CommunityConstants.QUESTION_CONTENT_TYPE_ID] = gs.getProperty('sn_communities.search.discussion.enable_acl') === 'true' ? true : false;
  		this.enableACL[sn_communities.CommunityConstants.BLOG_CONTENT_TYPE_ID] = gs.getProperty('sn_communities.search.blog.enable_acl') === 'true' ? true : false;
  		this.enableACL[sn_communities.CommunityConstants.DOCUMENT_CONTENT_TYPE_ID] = gs.getProperty('sn_communities.search.document.enable_acl') === 'true' ? true : false;
  		this.enableACL[sn_communities.CommunityConstants.EVENT_CONTENT_TYPE_ID] = gs.getProperty('sn_communities.search.event.enable_acl') === 'true' ? true : false;
  		this.enableACL[sn_communities.CommunityConstants.VIDEO_CONTENT_TYPE_ID] = gs.getProperty('sn_communities.search.video.enable_acl') === 'true' ? true : false;
  		this.SYS_ATTACHMENT = "sys_attachment";
  		this.IMAGE_URL = "/sys_attachment.do?sys_id=";
  		this.IIX_EXTN = ".iix";
  	}
  	this.NOTIF_OBJ_TABLE = "sn_actsub_notif_object";
  },
  
  createSubscription: function(subObjName, subObjId, subObjTypeId, subscriberId, streamId){
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.initialize();
  	gr.sub_obj_name = '' + subObjName;
  	gr.sub_obj_id = '' + subObjId;
  	gr.sub_obj_type = '' + subObjTypeId;
  	gr.subscriber_id = '' + subscriberId;
  	if(streamId)
  		gr.stream_id = '' + streamId;
  	else{
  		streamId = this._getDefaultStreamId(subscriberId);
  		gr.stream_id = '' + streamId;
  	}
  	gr.insert();
  	return gr.sys_id + '';
  },

  deleteSubscription: function(subscriberId, subObjId){
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery('sub_obj_id',subObjId);
  	gr.addQuery('subscriber_id',subscriberId);
  	gr.query();
  	if(gr.next()){
  		if(this.activitySubContext.isCommunityPluginActive == true && gr.sub_obj_type == this.SUB_OBJ_TOPIC && !sn_communities.CommunityConstants.ENABLE_TOPICS){
  			return 1;
  		}
  		gr.deleteRecord();
  		return 0;
  	}
  },
  /**
  *   This method allows to unsubscribe users
  *   from a give subscribable object
  *	Please use this method with caution as it deletes multiple
  *   subscription records
  **/
  unSubscribeUsers: function(sub_obj_id, users){
  	var result = {};
  	if(sub_obj_id){
  		var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  		gr.addQuery('sub_obj_id', sub_obj_id);
  		if(users) {
  			var liveProfileIDs = this.getLiveProfileIDs(users);
  			gr.addQuery('subscriber_id', "IN", liveProfileIDs);
  		}
  		gr.deleteMultiple();
  		result.unsubscribed_count = gr.getRowCount();
  	}
  	return result;
  },

  /**
   *   This method allows a set of users to subscribe
   *   from a give subscribable object
   *
   **/
  subscribeUsers: function (subObjTableName, subObjId, subObjTypeId, subscribersIds) {
  	var result = [],
  		len = 0;
  	try {
  		var users = this.getLiveProfileIDs(subscribersIds);
  		if (subObjId && users) {
  			users = users.split(',');
  			users = this.filterOutSubscribedUsers(subObjId,users);
  			len = users.length - 1;
  			while (len >= 0) {
  				result.push(this.createSubscription(subObjTableName, subObjId, subObjTypeId, users[len]));
  				len--;
  			}
  		}
  	} catch (exception) {
  		gs.info('An errors occured while creating subscriptions in SubscriptionDAO.subscribeUsers ' + exception);
  		return result;
  	}
  	return result;
  },

  isSubscribed: function(objectId, subscriberId)
  {
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery('sub_obj_id',objectId);
  	gr.addQuery('subscriber_id',subscriberId);
  	gr.query();
  	var retStatus = {};
  	if(gr.next()){
  		retStatus.subscriptionId = gr.sys_id + '';
  		retStatus.creationDate = gr.sys_created_on + '';
  	}
  	return retStatus;
  },

  /**
  *   This method takes in comma seperated value subObjectIds and a subObjectType
  *   returns subcription status for those subscribable objects.
  *   Returns a boolean array with each flag saying whether
  *   corresponding subobect in the subObjectIds is subcribed
  **/
  getSubscriptionStatusForSubObjects: function(subObjectIds, subObjectType){
  	var subscriberId = this.getLiveProfileId();
  	var subscriptionStatusListOfSubObjectIds = [];
  	if(gs.nil(subscriberId) || gs.nil(subObjectIds)){
  		return subscriptionStatusListOfSubObjectIds;
  	}
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery('sub_obj_id','IN', subObjectIds);
  	gr.addQuery('subscriber_id',subscriberId);
  	if(subObjectType)
  		gr.addQuery('sub_obj_type',subObjectType);
  	gr.query();
  	var subscriptionStatusMap = {};
  	while(gr.next()){
  		subscriptionStatusMap[gr.sub_obj_id+''] = true;
  	}
  	var subObjectIdList = subObjectIds.split(",");
  	subObjectIdList.forEach(function(subObjectId){
  		if(gs.nil(subObjectId+'')){
  			subscriptionStatusListOfSubObjectIds.push(false);
  			return;
  		}
  		var isSubscribed = false;
  		if(subscriptionStatusMap[subObjectId + '']){
  			isSubscribed = true;
  		}
  		subscriptionStatusListOfSubObjectIds.push(isSubscribed);
  	});
  	return subscriptionStatusListOfSubObjectIds;
  },

  filterOutSubscribedUsers: function(objectId, users)
  {
  	var subscribers = [];
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery('sub_obj_id',objectId);
  	gr.addQuery('subscriber_id','IN',users);
  	gr.query();
  	while(gr.next()){
  		subscribers.push(gr.getValue('subscriber_id'));
  	}
  	return new ArrayUtil().diff(users,subscribers);
  },

  getUserStream: function(profileId, streamName, skipCreation){
  	var userStream = new GlideRecord(this.ACTIVITY_USER_STREAM);
  	streamName = streamName || this.DEFAULT_STREAM;
  	userStream.addQuery('name',streamName);
  	userStream.addQuery('user_id',profileId);
  	userStream.query();

  	if(userStream.next())
  		return {"streamId":userStream.sys_id + '',"name":userStream.name + '',
  				"fanout_to_stream":userStream.fanout_to_stream == true,"is_user_stream":userStream.is_user_stream + ''};
  	if(skipCreation)
  		return;
  	else{
  		var streamId = this.createUserStream(profileId);//Create default stream if not present
  		return {"streamId":streamId + '',"name":this.DEFAULT_STREAM,
  				"fanout_to_stream": true, "is_user_stream": false};
  	}

  },
  _getUsersWithFanoutDisabled: function(profileIDs, streamName){
  	var profileList;
  	if(profileIDs && profileIDs.length > 0){
  		profileList = new global.ArrayUtil().unique(profileIDs).join(',');
  	}
  	var userStream = new GlideRecord(this.ACTIVITY_USER_STREAM);
  	streamName = streamName || this.DEFAULT_STREAM;
  	userStream.addQuery('name',streamName);
  	userStream.addQuery('user_id', 'IN', profileList);
  	userStream.addQuery('fanout_to_stream', false);		
  	userStream.query();

  	var users = [];
  	while(userStream.next()){
  		users.push(userStream.user_id + '');
  	}
  	return users;
  },
  _getDefaultStreamId: function(profileId){
  	var defaultStream = this.getUserStream(profileId, this.DEFAULT_STREAM);
  	if(defaultStream)
  		return defaultStream.streamId;
  },
  createUserStream: function(profileId, streamName, fanoutToStream){
  	var result = this.getUserStream(profileId, streamName, true);
  	if(result)
  		return {"status": 400, "message": "stream already exists"};
  	var userStream = new GlideRecord(this.ACTIVITY_USER_STREAM);
  	userStream.initialize();
  	userStream.name = streamName || this.DEFAULT_STREAM;
  	userStream.user_id = profileId;
  	if(fanoutToStream == false)
  		userStream.fanout_to_stream = false;
  	else
  		userStream.fanout_to_stream = true;
  	userStream.setValue('last_accessed_on', new GlideDateTime());
  	userStream.insert();
  	return userStream.sys_id;
  },
  updateUserStream: function(profileId, streamName, fanoutToStream){
  	var userStream = new GlideRecord(this.ACTIVITY_USER_STREAM);
  	streamName = streamName || this.DEFAULT_STREAM;
  	userStream.addQuery('name',streamName);
  	userStream.addQuery('user_id',profileId);
  	userStream.query();
  	if(!userStream.hasNext()){
  		userStream.user_id = profileId;
  		userStream.name = streamName;
  	}
  	else
  		userStream.next();
  	if(!userStream.canWrite() || !userStream.canCreate()){
  		return {"status": 400, "result":"User doesn't have access to update stream"};
  	}
  	userStream.fanout_to_stream = fanoutToStream || false;
  	userStream.setValue('last_accessed_on', new GlideDateTime());
  	userStream.update();//if record doesn't exist, it will insert a new record
  	return {"streamId":userStream.sys_id + '',"name":userStream.name + '',
  			"fanout_to_stream":userStream.fanout_to_stream + '',"is_user_stream":userStream.is_user_stream + '',
  			"result:": "user stream is updated."};

  },
  getSubscribableObjectNames: function(){
  	var sub_objs = new GlideRecordSecure(this.SUB_OBJ_TABLE);
  	sub_objs.query();
  	while(sub_objs.next()){
  		this.Results.push(sub_objs.name.toString());
  	}
  	return this.Results.join(',');
  },

  getSubscribableObjectInfo: function(subObjTypeId){
  	var sub_obj = new GlideRecordSecure(this.SUB_OBJ_TABLE);
  	if(subObjTypeId)
  		sub_obj.addQuery('sys_id',subObjTypeId);
  	sub_obj.query();

  	if(sub_obj.next())
  		return {"name":sub_obj.name,"table_name":sub_obj.table_name,"sys_id":sub_obj.sys_id};
  	else return null;
  },
  getSubObjByTableName: function(tableName){
  	var sub_obj = new GlideRecord(this.SUB_OBJ_TABLE);
  	if(tableName)
  		sub_obj.addQuery('table_name',tableName);
  	sub_obj.query();

  	if(sub_obj.next())
  		return sub_obj.sys_id;
  },
  getSubscribableObjects: function(setupPref, module){
  	var subObjects = [], temp = [];
  	var gr = new GlideRecordSecure(this.SUB_OBJ_TABLE);
  	if(parseInt(setupPref) == 1)
  		gr.addEncodedQuery("sys_id=6cbd03c467103200ace49a6617415ac4^ORsys_id=17bd03c467103200ace49a6617415aed");
  	if(this.activitySubContext.isCommunityPluginActive == true && !sn_communities.CommunityConstants.ENABLE_TOPICS)
  		gr.addQuery('sys_id', '!=', this.SUB_OBJ_TOPIC);
  	gr.addQuery('module', module);
  	gr.orderBy('order');
  	gr.query();

  	while(gr.next()){
  		if(gr.table_name == 'sn_actsub_subscribable_object')
  			continue;
  		var obj = {};
  		obj.name = gr.getDisplayValue('name');
  		obj.order = gr.getValue('order');
  		obj.sys_id = gr.getUniqueValue();
  		obj.table_name = gr.getValue('table_name');
  		obj.framework = 'actsub';
  		subObjects.push(obj);
  	}

  	//get the legacy Notifications objects
  	var ng = new GlideRecord(this.NOTIF_OBJ_TABLE);
  	ng.addActiveQuery();
  	ng.addQuery('module', module);
  	ng.orderBy('order');
  	ng.query();
  	while (ng.next()) {
  		if (ng.canRead()) {
  			var obj = {};
  			obj.name = ng.getDisplayValue('name');
  			obj.order = ng.getValue('order');
  			obj.sys_id = ng.getUniqueValue();
  			obj.table_name = ng.getValue('table_name');
  			obj.noti_category = ng.getValue('notification_category');
  			obj.framework = 'legacy';
  			temp.push(obj);
  		}
  	}

  	if (temp.length > 0) {
  		if (!subObjects.length)
  			subObjects = temp;
  		else {
  			// add into subObjects array in sorted manner
  			var start_from = 0;
  			temp.forEach(function(obj) {
  				for (var i = start_from; i < subObjects.length; i++ ) {
  					if (subObjects[i].order > obj.order) {
  						subObjects.splice(i, 0, obj);
  						start_from = i + 1;
  						break;
  					}
  				} 
  			});	
  		}
  	}
  	
  	return subObjects;
  },
  getSubscribersCount: function(subObjId, objType){
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery("sub_obj_type", objType);
  	gr.addQuery("sub_obj_id", subObjId);
  	gr.query();
  	return gr.getRowCount();
  },

  getSubscribers: function(objectIds, actor, checkNotifPreference, author, isFeedback){
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery('sub_obj_id','IN',objectIds);
  	if(actor)
  		gr.addQuery('subscriber_id','!=',actor);
  	if(author && isFeedback)
  		gr.addQuery('subscriber_id','!=',author);
  	gr.query();
  	var subscribersProfIds = [];
  	var subscribersSysIds = [];
  	var sysIdToliveProfileMap = {};
  	var liveProfileToSysIdMap = {};		
  	while(gr.next()){
  		var subscriber = this.getLiveProfileRec(gr.subscriber_id);
  		sysIdToliveProfileMap[subscriber.document + ''] = gr.subscriber_id + '';
  		liveProfileToSysIdMap[gr.subscriber_id + ''] = subscriber.document + '';
  		subscribersSysIds.push(subscriber.document + '');
  		subscribersProfIds.push(gr.subscriber_id + '');
  	}
  	if(checkNotifPreference){
  		this.filterSubscribersByGlobalPreferences(sysIdToliveProfileMap, subscribersProfIds, liveProfileToSysIdMap, subscribersSysIds);
  	}
  	return {subProfIds:subscribersProfIds, subSysIds: subscribersSysIds};
  },

  filterSubscribersByGlobalPreferences: function(sysIdToliveProfileMap, subscribersProfIds, liveProfileToSysIdMap, subscribersSysIds) {
  	try{
  		//filter by global preference				
  		var usersList;
  		if(subscribersSysIds && subscribersSysIds.length > 0){
  			usersList = new global.ArrayUtil().unique(subscribersSysIds).join(',');
  		}
  		//Filter based on global notification preference
  		gr = new GlideRecord('sys_user');
  		gr.addQuery('sys_id', 'IN', usersList);
  		//Get the negative list which should be smaller.
  		gr.addQuery('notification', '<>' , this.GLOBAL_NOTIF_PREF_ENABLE_VAL);
  		gr.query();
  		while(gr.next()){
  			var index = subscribersSysIds.indexOf(gr.sys_id + '');
  			if(index > -1)
  				subscribersSysIds.splice(index, 1);
  			var profileId = sysIdToliveProfileMap[gr.sys_id + ''];
  			index = subscribersProfIds.indexOf(profileId);
  			if(index > -1)	
  				subscribersProfIds.splice(index, 1);
  		}
  	}catch(err){
  		gs.error('ACTSUB-ERROR: Unable to filter by global preference');
  	}
  	//Filter by fanout preference
  	try{
  		var disabledFanoutArray = this._getUsersWithFanoutDisabled(subscribersProfIds, 'Notification');
  		if(disabledFanoutArray && disabledFanoutArray.length > 0){
  			for(var idx in  disabledFanoutArray){
  				var i = subscribersProfIds.indexOf(disabledFanoutArray[idx]);
  				if(i > -1)	
  					subscribersProfIds.splice(i, 1);
  				var sysID = liveProfileToSysIdMap[disabledFanoutArray[idx]];
  				i = subscribersSysIds.indexOf(sysID);
  				if(i > -1)
  					subscribersSysIds.splice(i, 1);
  			}
  		}
  	}catch(err){
  		gs.error('ACTSUB-ERROR: Unable to filter by fanout preference');
  	}
  	return {subProfIds:subscribersProfIds, subSysIds: subscribersSysIds};
  },

  filterUsersByGlobalPreferences: function(userIds) {
  	if(!userIds || userIds.length == 0)
  		return;
  	var _users = [].concat(userIds);
  	var gr = new GlideRecord("live_profile");
  	gr.addQuery('document', 'IN', _users.join());
  	gr.addQuery('type', 'user');
  	gr.query();
  	
  	var subscribersProfIds = [];
  	var subscribersSysIds = [];
  	var sysIdToliveProfileMap = {};
  	var liveProfileToSysIdMap = {};		
  	while(gr.next()){
  		sysIdToliveProfileMap[gr.document + ''] = gr.sys_id + '';
  		liveProfileToSysIdMap[gr.sys_id + ''] = gr.document + '';
  		subscribersSysIds.push(gr.document + '');
  		subscribersProfIds.push(gr.sys_id + '');
  		var idx = _users.indexOf(gr.document+'');
  		if(idx > -1)
  			_users.splice(idx, 1);
  	}
  	if(_users.length > 0) {
  		for(var i=0; i< _users.length; i++)
  			subscribersSysIds.push(_users[i]);
  	}
  	var usersObject = this.filterSubscribersByGlobalPreferences(sysIdToliveProfileMap, subscribersProfIds, liveProfileToSysIdMap, subscribersSysIds);
  	if(usersObject && usersObject.subSysIds)
  		return usersObject.subSysIds;
  },

  getSubscribersBySubscription: function(subObjId, subObjType, orderBy, firstRow, lastRow,
  										searchString, fetchCount, dontFetchSubscriberInfo){
  	if(!subObjId)
  		return;
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	var retObj = {};
  	var sessionUserProfileId = this.getLiveProfileId();
  	gr.addQuery('sub_obj_id',subObjId);
  	if(subObjType)
  		gr.addQuery('sub_obj_type', subObjType);
  	if(orderBy && orderBy == 'recent')
  		gr.orderByDesc('sys_created_on');
  	else if(orderBy == 'subscriber')
  		gr.orderBy('subscriber_id');
  	try{
  		firstRow = parseInt(firstRow);
  		lastRow = parseInt(lastRow);
  		firstRow = isNaN(firstRow) ? 0 : firstRow;
  		lastRow = isNaN(lastRow) ? this.MAX_PAGE_SIZE : lastRow;
  		//default to max page size
  		if((lastRow-firstRow) > this.MAX_PAGE_SIZE)//Always set the page size less than or equal to MAX_PAGE_SIZE
  			lastRow = firstRow + this.MAX_PAGE_SIZE;
  	}catch(err){
  		//default to first 15 records
  		firstRow = 0;
  		lastRow = this.MAX_PAGE_SIZE;
  	}
  	if(firstRow > -1 && lastRow > -1 && lastRow >= firstRow){
  		gr.chooseWindow(firstRow, lastRow);//force count total records
  	}

  	searchString = searchString ? searchString.toString() : "";
  	if(searchString){
  		var comm_profile_gr = new GlideRecord(sn_communities.CommunityConstants.SN_COMMUNITIES_PROFILE);
  		comm_profile_gr.addQuery('name','CONTAINS',searchString);
  		comm_profile_gr.query();
  		
  		var liveprofileIds=[];
  		while(comm_profile_gr.next()){
  			liveprofileIds.push(comm_profile_gr.getValue('live_profile'));
  		}
  		if(liveprofileIds.length > 0){
  			gr.addQuery('subscriber_id','IN',liveprofileIds);
  		}
  		else{
  			retObj.searchString = searchString;
  			retObj.hasMoreRecords = false;
  			retObj.recordCount = 0;
  			if(fetchCount && fetchCount == "subscriptions"){
  				retObj.subscriptionsCount = 0;
  			}
  			retObj.subscribers = [];
  			return retObj;
  		}
  	}
  	
  	gr.query();
  	
  	retObj.searchString = searchString;
  	if(gr.getRowCount() > lastRow)
  		retObj.hasMoreRecords = true;
  	retObj.recordCount = gr.getRowCount();
  	if(fetchCount && fetchCount == "subscriptions"){// && fetchSubscriptionsCount == true){
  		retObj.subscriptionsCount = this.getSubscriptionsCount(subObjId, subObjType);
  	}
  	var result = [];
  	while(gr.next()){
  		var subscription = {};
  		subscription.subscriber_id = '' + gr.subscriber_id;
  		subscription.subscriber_sys_user_id = '' + gr.subscriber_id.document;
  		subscription.subscriber_name = '' + gr.subscriber_id.getDisplayValue();
  		subscription.title = '' + gr.subscriber_id.document.title;

  		if(!dontFetchSubscriberInfo) {
  			var isSubscribed;
  			if(gs.isLoggedIn())//get this information only for loggedin users
  				isSubscribed = this.isSubscribed(subscription.subscriber_id, sessionUserProfileId);
  			if(isSubscribed && isSubscribed.subscriptionId){
  				subscription.sessionUserSubscribed = true;
  			}else
  				subscription.sessionUserSubscribed = false;
  			var image = this.getImageURL(subscription.subscriber_id);
  			subscription.image = {};
  			subscription.image.userImage = image.iix;
  			subscription.image.userID = '' + gr.subscriber_id.document;
  			subscription.image.userName = '' + gr.subscriber_id.name;
  			subscription.image.isLoaded = true;
  			subscription.image.initials = this._getUserInitials(gr.subscriber_id.name);
  			if(this.activitySubContext.isCommunityPluginActive == true && gr.sub_obj_type != this.SUB_OBJ_KB && gr.sub_obj_type != this.SUB_OBJ_KA){
  				var profileImpl = new sn_communities.Community_Factory().getWrapperType(sn_communities.CommunityConstants.PROFILE);
  				var profileDetails = profileImpl.getUserProfile(subscription.subscriber_id);
  				var commProfileName = (profileDetails && profileDetails.display_name && profileDetails.display_name.value) ? profileDetails.display_name.value : "";
  				if(profileDetails && profileDetails.title)
  					subscription.title = profileDetails.title;
  				if(profileDetails && profileDetails.company)
  					subscription.company = profileDetails.company;
  				if(profileDetails && profileDetails.photo)
  					subscription.image.userImage = profileDetails.photo.value;
  				if(commProfileName) {
  					subscription.subscriber_name = commProfileName;
  					subscription.image.userName = commProfileName;
  					subscription.image.initials = this._getUserInitials(commProfileName);
  				}
  			}
  		}
  		result.push(subscription);
  	}
  	retObj.subscribers = result;
  	return retObj;
  },
  getSubObjGlblPref: function(current){
  	var gr = new GlideRecord(this.SUB_OBJ_NOTIF_PREF);
  	gr.addQuery('activity_type',current.activity_type_id);
  	gr.addQuery('is_global', true);
  	gr.query();
  	var map = {};
  	while(gr.next()){
  		map[gr.subscribable_object.table_name] = gr.getValue('preference_code');
  	}
  	return map;
  },
  getSubscriptions: function(profile){
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery('subscriber_id',profile);
  	gr.query();
  	var result = [];
  	while(gr.next()){
  		if(!gr.canRead())
  			continue;
  		if(this.activitySubContext.isCommunityPluginActive == true
  		   && gr.sub_obj_id.content && !gr.sub_obj_id.content.active)
  			continue;
  		result.push(gr.sub_obj_id.toString());
  	}
  	return result.join(',');
  },
  getSubscriptionsCount: function(profile, subObjType){
  	var gr = new GlideRecordSecure(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery('subscriber_id',profile);
  	if(subObjType)
  		gr.addQuery('sub_obj_type', subObjType);
  	gr.query();
  	return gr.getRowCount();
  },
  getLiveProfileId: function(userId){
  	userId = userId || gs.getUserID();
  	var profile_id = new GlideappLiveProfile().getID(userId);
  	return profile_id;
  },
  getLiveProfileIDs: function(userIds){
  	if(userIds){
  		var liveProfileIds;
  		var live_profile = new GlideRecord("live_profile");
  		live_profile.addQuery("document", "IN", userIds);
  		live_profile.query();
  		while(live_profile.next()){
  			if(liveProfileIds)
  				liveProfileIds += live_profile.getUniqueValue() + '';
  			else
  				liveProfileIds = live_profile.getUniqueValue() + '';
  			if(live_profile.hasNext())
  				liveProfileIds += ',';
  		}
  		return liveProfileIds;
  	}
  },
  getLiveProfileRec: function(profileId){
  	var live_profile = new GlideRecord("live_profile");
  	live_profile.addQuery("sys_id", profileId);
  	live_profile.query();
  	if(live_profile.next())
  		return live_profile;
  },

  getActSubCounts: function(liveProfileId, onlyActCount, onlySubsCount){
  	if(!liveProfileId)
  		liveProfileId = this.getLiveProfileId(gs.getUserID());//Get session user profile Id.
  	var streamId = this.activitySubContext.getActivityDAO().getStreamID(this.DEFAULT_STREAM, liveProfileId);
  	var	result = {};
  	if(streamId && !onlySubsCount){
  		var	activityCount = this.activitySubContext.getActivityDAO().getActivitiesCountByUserInStream(streamId, liveProfileId, true);
  		result.activityStreamCount = activityCount;
  	}

  	if (!onlyActCount) {
  		var ga = new GlideAggregate(this.SUBSCRIPTIONS_TABLE);
  		ga.addQuery('subscriber_id',liveProfileId);
  		ga.addQuery('sub_obj_type', '<>', this.SUB_META_OBJ_SYS_ID);
  		ga.addAggregate('COUNT');
  		ga.query();
  		var subscriptionsCount = 0;
  		if(ga.next())
  			subscriptionsCount = ga.getAggregate('COUNT');

  		result.subscriber = liveProfileId;
  		result.subscriptionsCount = subscriptionsCount;
  	}
  	return result;
  },
  getSubscribedForum : function(forumList){
  	var subscribedforums = [];
  	if(forumList != null && forumList){
  		var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  		var sessionUserProfileId = this.getLiveProfileId();
  		gr.addQuery('sub_obj_id','IN',forumList.join());
  		gr.addQuery('subscriber_id',sessionUserProfileId);
  		gr.query();
  		while(gr.next()){
  			subscribedforums.push(gr.sub_obj_id.toString());
  		}
  	}
  	return subscribedforums;

  },
  getSubscriptionsBySubscriber: function(profile, subObjType, getList, orderBy, firstRow, lastRow, searchString){
  	var userLiveProfile;
  	var sessionUserProfileId = this.getLiveProfileId();//get current session user profile ID
  	if(getList == "true")
  		userLiveProfile = this.getLiveProfileId();
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	if(getList == "true")
  		gr.addQuery('subscriber_id',userLiveProfile);
  	else
  		gr.addQuery('subscriber_id',profile);
  	gr.addQuery('sub_obj_type','!=', this.SUB_META_OBJ_SYS_ID);
  	if(subObjType)
  		gr.addQuery('sub_obj_type',subObjType);
  	try{
  		firstRow = parseInt(firstRow);
  		lastRow = parseInt(lastRow);
  		firstRow = isNaN(firstRow) ? 0 : firstRow;
  		lastRow = isNaN(lastRow) ? this.MAX_PAGE_SIZE : lastRow;
  		if((lastRow-firstRow) > this.MAX_PAGE_SIZE)//Always set the page size less than or equal to MAX_PAGE_SIZE
  			lastRow = firstRow + this.MAX_PAGE_SIZE;
  	}catch(err){
  		firstRow = 0;
  		lastRow = this.MAX_PAGE_SIZE;
  	}
  	gr.chooseWindow(firstRow, lastRow);
  	if(orderBy == 'recent')
  		gr.orderByDesc('sys_created_on');
  	gr.query();
  	var hasMoreRecords = gr.getRowCount() > lastRow;
  	var subscriptionsCount = gr.getRowCount();
  	var result = [];
  	var resultIds = [];
  	var subscriber;
  	searchString = searchString ? searchString.toString() : "";
  	var accessibleForums = {};
  	while(gr.next()){
  		var subscription = {}, profileDetails, profileImpl;
  		subscription.sub_obj_type = '' + gr.sub_obj_type.getDisplayValue();
  		subscription.sub_obj_id = '' + gr.sub_obj_id;
  		subscription.sub_obj_display_value = gr.sub_obj_id.getDisplayValue();

  		if(this.activitySubContext.isCommunityPluginActive == true && gr.sub_obj_type == this.SUB_OBJ_LIVE_PROFILE && gr.sub_obj_type != this.SUB_OBJ_KB && gr.sub_obj_type != this.SUB_OBJ_KA){
  			var image = this.getImageURL(subscription.sub_obj_id);
  			subscription.image = {};
  			subscription.image.userImage = image.iix;
  			subscription.image.userID = gr.sub_obj_id.document;
  			subscription.image.userName = gr.sub_obj_id.name + '';
  			subscription.image.isLoaded = true;
  			subscription.image.initials = this._getUserInitials(gr.sub_obj_id.name);
  			profileImpl = new sn_communities.Community_Factory().getWrapperType(sn_communities.CommunityConstants.PROFILE);
  			profileDetails = profileImpl.getUserProfile(subscription.sub_obj_id);
  			if(profileDetails && profileDetails.display_name && profileDetails.display_name.value)
  				subscription.image.userName = profileDetails.display_name.value;
  			if(profileDetails && profileDetails.title)
  				subscription.title = profileDetails.title;
  			if(profileDetails && profileDetails.company)
  				subscription.company = profileDetails.company;
  			if(profileDetails && profileDetails.photo)
  				subscription.image.userImage = profileDetails.photo.value;
  		}
  		//Implement search on document_id field
  		if(searchString && searchString.length > 0
  		   && subObjType == this.SUB_OBJ_LIVE_PROFILE){
  			var profileName = subscription.image.userName;
  			if(profileName && profileName.toLowerCase().indexOf(searchString.toLowerCase()) == -1)
  				continue;
  		}
  		if(getList == "true")
  			resultIds.push(gr.sub_obj_id.toString());
  		else {
  			if(this.activitySubContext.isCommunityPluginActive == true
  			   && gr.sub_obj_id.content && !gr.sub_obj_id.content.active)
  				continue;
  			subscriber = gr.subscriber_id.getDisplayValue();
  			var hasAccess = true;
  			var forumId, contentTypeId, evalAcl = true;
  			if(this.activitySubContext.isCommunityPluginActive == true
  			   && gr.sub_obj_type != this.SUB_OBJ_KB//Knowledge Base
  			   && gr.sub_obj_type != this.SUB_OBJ_KA //Knowledge Article
  			   && gr.sub_obj_type != this.SUB_OBJ_IDEA){ //Idea
  				profileImpl = new sn_communities.Community_Factory().getWrapperType(sn_communities.CommunityConstants.PROFILE);
  				profileDetails = profileImpl.getUserProfile(gr.subscriber_id + '');
  				if(profileDetails && profileDetails.display_name && profileDetails.display_name.value) {
  					subscriber = profileDetails.display_name.value;
  				}
  				if(gr.sub_obj_id.content){
  					forumId = gr.sub_obj_id.content.forum_id;
  					contentTypeId = gr.sub_obj_id.content.content_type;
  				}
  				if(contentTypeId && this.enableACL[contentTypeId] == false
  				   && accessibleForums[forumId] && accessibleForums[forumId][contentTypeId]){
  					hasAccess = accessibleForums[forumId][contentTypeId];
  					evalAcl = false;
  				}
  				if(evalAcl == true)
  					hasAccess = new sn_communities.CommunityActivityService().hasAccessToSubscription(gr);
  				if(forumId && contentTypeId){
  					if(!accessibleForums[forumId])
  						accessibleForums[forumId] = {};
  				}
  				if(!hasAccess){
  					if(forumId && contentTypeId && this.enableACL[contentTypeId] == false)
  						accessibleForums[forumId][contentTypeId] = false;
  					continue;
  				}
  				if(forumId && contentTypeId && this.enableACL[contentTypeId] == false)
  					accessibleForums[forumId][contentTypeId] = true;
  			}
  			var gdt = new GlideDateTime(gr.sys_created_on + '');
  			subscription.sys_created_on = gdt.getNumericValue();
  			if(sessionUserProfileId && sessionUserProfileId != profile){
  				//viewing others profile and subscriptions, so store the session's users status of subscription
  				// with respect to other users subscriptions.
  				var retStatus = this.isSubscribed(subscription.sub_obj_id, sessionUserProfileId);
  				if(retStatus && retStatus.subscriptionId)
  					subscription.sessionUserSubscribed = true;
  				else
  					subscription.sessionUserSubscribed = false;
  			}else{
  				subscription.sessionUserSubscribed = true;
  			}
  			if(this.activitySubContext.isCommunityPluginActive == true){
  				if(gr.sub_obj_type == this.SUB_OBJ_FORUM){
  					subscription.parent = '' + gr.sub_obj_id.parent;
  					subscription.description = '' + gr.sub_obj_id.description;
  				}
  			}
  			//Additional information for question objects
  			if(this.activitySubContext.isCommunityPluginActive == true
  			   && gr.sub_obj_id.content){
  				subscription.content_details = new sn_communities.CommSubscriptionDAO().getContentObject(gr);
  				if(subscription.content_details)
  					result.push(subscription);
  			}
  			else
  				result.push(subscription);
  		}
  	}
  	if(getList == "true") {
  		resultIds = resultIds.join(',');
  		return {"subscriptions":resultIds};
  	}
  	else{
  		return {"subscriber":subscriber,"subscriber_id":profile,"subscriptions":result, "hasMoreRecords":hasMoreRecords, "subscriptionsCount": subscriptionsCount,
  				"firstRow": firstRow, "lastRow": lastRow};
  	}
  },
  /**
   A more effecient method specifically designed to capture user subscriptions to show-up on the community follow page
   and does some optimization in fetching the profile details and doesn't pollute the getSubscriptionsBySubscriber method
  **/
  getFollowingsByFollower: function(profile, subObjType, orderBy, firstRow, lastRow, searchString){
  	var userLiveProfile;
  	var sessionUserProfileId = this.getLiveProfileId();//get current session user profile ID
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery('subscriber_id',profile);
  	gr.addQuery('sub_obj_type','!=', this.SUB_META_OBJ_SYS_ID);
  	if(subObjType)
  		gr.addQuery('sub_obj_type',subObjType);
  	else
  		gr.addQuery('sub_obj_type',this.SUB_OBJ_LIVE_PROFILE);
  	gr.query();
  	var subscriptionsCount = gr.getRowCount(), subscriber;
  	//Get the followers count
  	var followersCount = this.getSubscribersCount(profile, this.SUB_OBJ_LIVE_PROFILE);
  	var subscriptions = [], followingIDs = [];
  	searchString = searchString ? searchString.toString() : "";
  	while(gr.next()){
  		var subscription = {};
  		subscriber = gr.subscriber_id.getDisplayValue();
  		subscription.sub_obj_type = '' + gr.sub_obj_type.getDisplayValue();
  		subscription.sub_obj_id = '' + gr.sub_obj_id;
  		subscription.sub_obj_display_value = gr.sub_obj_id.getDisplayValue();
  		var gdt = new GlideDateTime(gr.sys_created_on + '');
  		subscription.sys_created_on = gdt.getNumericValue();

  		//fetch the initial data from live profile, in case the community profile is not available.
  		//later outside the while, these values are overridden from community profile.
  		var image = this.getImageURL(subscription.sub_obj_id);
  		subscription.image = {};
  		subscription.image.userImage = image.iix;
  		subscription.image.userID = gr.sub_obj_id.document;
  		subscription.image.userName = gr.sub_obj_id.name + '';
  		subscription.image.isLoaded = true;
  		subscription.image.initials = this._getUserInitials(gr.sub_obj_id.name);
  		if(sessionUserProfileId && sessionUserProfileId != profile){
  			//viewing others profile and subscriptions, so store the session's users status of subscription
  			// with respect to other users subscriptions.
  			var retStatus = this.isSubscribed(subscription.sub_obj_id, sessionUserProfileId);
  			if(retStatus && retStatus.subscriptionId)
  				subscription.sessionUserSubscribed = true;
  			else
  				subscription.sessionUserSubscribed = false;
  		}else{
  			subscription.sessionUserSubscribed = true;
  		}

  		followingIDs.push(subscription.sub_obj_id);
  		subscriptions.push(subscription);
  	}
  	var resultArray = [];
  	if(this.activitySubContext.isCommunityPluginActive == true
  	   && followingIDs && followingIDs.length > 0 && gr.sub_obj_type != this.SUB_OBJ_KB && gr.sub_obj_type != this.SUB_OBJ_KA){

  		var profileImpl = new sn_communities.Community_Factory().getWrapperType(sn_communities.CommunityConstants.PROFILE);
  		var profileDetails = profileImpl.getUserInfo(followingIDs, ['photo','display_name','title','company']);
  		if(profileDetails){
  			for(var index=0;index<subscriptions.length;index++){
  				var subObj = subscriptions[index];
  				var communityProfile = profileDetails[subObj.sub_obj_id];
  				//Implement search on document_id field
  				if(communityProfile){
  					var profileName = communityProfile.name ? communityProfile.name : subObj.image.userName;
  					//If the name doesn't match the search string remove the subscription from the result.
  					if(profileName && searchString && searchString.length > 0
  					   && profileName.toLowerCase().indexOf(searchString.toLowerCase()) == -1){
  						continue;
  					}
  					//override the live profile details from community profile details.
  					if(communityProfile.name) {
  						subObj.image.userName = communityProfile.name;
  						subObj.sub_obj_display_value = communityProfile.name;
  						subscriber = communityProfile.name;
  					}
  						
  					if(communityProfile.title){
  						subObj.title = {};
  						subObj.title.value = communityProfile.title;
  					}
  					if(communityProfile.company){
  						subObj.company = {};
  						subObj.company.value = communityProfile.company;
  					}
  					if(communityProfile.userImage)
  						subObj.image.userImage = communityProfile.userImage;
  					if(communityProfile.initials)
  						subObj.image.initials = communityProfile.initials;
  				}
  				resultArray.push(subObj);
  			}
  		}
  	}
  	//implement sorting and searching on the resulting array
  	//because document_id field cannot be sorted by GR
  	var hasMoreRecords = false;
  	if(resultArray.length > 0){
  		try{
  			firstRow = parseInt(firstRow);
  			lastRow = parseInt(lastRow);
  		}catch(err){
  			//default to first 15 records
  			firstRow = 0;
  			lastRow = 15;
  		}
  		if(resultArray.length > lastRow)
  			hasMoreRecords = true;

  		if(orderBy && orderBy == 'recent'){
  			resultArray.sort(this._compareSubscriptionsByRecent);
  		}else if(orderBy && orderBy == 'subscription'){
  			resultArray.sort(this._compareSubscriptionsByName);
  		}
  		if(firstRow > -1 && lastRow > -1 && lastRow >= firstRow){
  			resultArray = resultArray.slice(firstRow, lastRow);
  		}
  	}
  	return {"subscriber":subscriber,"subscriber_id":profile,"subscriptions":resultArray, "hasMoreRecords":hasMoreRecords, "subscriptionsCount": subscriptionsCount, "followersCount": followersCount};
  },
  _compareSubscriptionsByName: function(subscriptionA, subscriptionB){
  	if(subscriptionA.image.userName && subscriptionB.image.userName){
  		return subscriptionA.image.userName.localeCompare(subscriptionB.image.userName);
  	}
  },
  _compareSubscriptionsByRecent: function (subscriptionA, subscriptionB){
  	if(subscriptionA.sys_created_on && subscriptionB.sys_created_on){
  		return subscriptionB.sys_created_on - subscriptionA.sys_created_on;
  	}
  }	,
  _getUserInitials: function (name){
  	if (!name)
  		return "--";

  	var initials = name.split(" ").map(function(word) {
  		return word.toUpperCase();
  	}).filter(function(word) {
  		return word.match(/^[A-Z]/);
  	}).map(function(word) {
  		return word.substring(0,1);
  	}).join("");

  	return (initials.length > 3)? initials.substr(0, 3): initials;
  },
  getImageURL: function(forum_id){
  	var gr = new GlideRecord(this.SYS_ATTACHMENT);
  	gr.addQuery("table_sys_id",forum_id);
  	gr.query();
  	var image = {};
  	if(gr.next()){
  		image.url = '' + this.IMAGE_URL + gr.sys_id;
  		image.iix = '' + gr.sys_id + this.IIX_EXTN;
  	}
  	return image;
  },
  getPreferences: function(profileId, subObject, activityTypeId){
  	var preferences = {};
  	var liveProfile = this.getLiveProfileRec(profileId);
  	preferences.user = {
  		"profile_id": liveProfile.sys_id + '',
  	};

  	if (!this.canFetchPreferences(liveProfile.document + ''))
  		throw {
  			message: "Security Error: User fetching preferences are different from preference record user!"
  		};
  	
  	var gr = new GlideRecord(this.ACTIVITY_TYPE_PREF);
  	if(activityTypeId)
  		gr.addQuery('activity_type', activityTypeId);
  	gr.addQuery('subscribable_object', subObject);
  	gr.addQuery('is_global', true);
  	gr.orderBy('activity_type.label');
  	gr.query();
  	preferences.activities = [];
  	//Get user default preference code, if not present use global
  	var prefMap;


  	while(gr.next()){
  		if(!preferences.sub_object.sys_id){
  			//Executes only first time to set the subscribable object details.
  			preferences.sub_object = {};
  			preferences.sub_object.sys_id = gr.subscribable_object.sys_id + '';
  			preferences.sub_object.name = gr.subscribable_object.name + '';
  			//Get the map of activity_type and default preference codes for the user
  			prefMap = this._getDefaultUserPrefCodes(profileId, gr.subscribable_object.sys_id);
  		}
  		var	prefCode;
  		if(prefMap[gr.activity_type])
  			prefCode = prefMap[gr.activity_type].preference_code;
  		else
  			prefCode = gr.preference_code;
  		try{
  			prefCode = parseInt(prefCode);
  		}catch(err){
  			prefCode = 0;
  		}
  		preferences.activities.push({activity_type_id:'' + gr.activity_type,
  									 short_description:'' + gr.activity_type.short_description,
  									 label: '' + gr.activity_type.label,
  									 pref_code: {
  										 user_default: prefCode
  									 }
  									});
  	}
  	return preferences;
  },
  _getDefaultUserPrefCodes: function(profileId, subObjId){
  	var userSubscription = this.isSubscribed(subObjId, profileId);
  	var prefMap = {};
  	if(userSubscription && userSubscription.subscriptionId){
  		prefMap.subscriptionId = userSubscription.subscriptionId + '';
  		var gr = new GlideRecord(this.SUB_NOTIF_PREF);
  		gr.addQuery('subscription', userSubscription.subscriptionId);
  		gr.query();
  		while(gr.next()){
  			var key = gr.notification_preference.activity_type + '';
  			var value = gr.notification_preference.preference_code + '';
  			prefMap[key] = {"preference_code" : value,
  							'sys_id': gr.sys_id + ''};
  		}
  	}else{
  		//first time setup, create subscription at default level
  		prefMap.subscriptionId = this.createSubscription('sn_actsub_subscribable_object', subObjId, this.SUB_META_OBJ_SYS_ID, profileId);
  	}
  	return prefMap;
  },
  updatePreferences: function(prefData){
  	var result;
  	if(prefData.user.profile_id && prefData.sub_object.sys_id){
  		var profileRec = this.getLiveProfileRec(prefData.user.profile_id);
  		if(profileRec.document != gs.getUserID()){//Don't allow other users to update preferences through API.
  			throw {message:"Security Error: User updating preferences is different from preference record user!"};
  		}
  		var prefMap = this._getDefaultUserPrefCodes(prefData.user.profile_id, prefData.sub_object.sys_id);

  		var activities = [];
  		activities = prefData.sub_object.activities;

  		if(activities){
  			result = [];
  			for(var i=0; i < activities.length;i++){
  				if(prefMap[activities[i].activity_type_id] && (prefMap[activities[i].activity_type_id].preference_code == activities[i].preferences['default']))
  					continue;//Its same, no need to update/insert

  				//Get a unique tuple if present
  				var gr = new GlideRecord(this.ACTIVITY_TYPE_PREF);
  				gr.addQuery('subscribable_object', prefData.sub_object.sys_id);
  				gr.addQuery('activity_type', activities[i].activity_type_id);
  				gr.addQuery('is_global', false);
  				gr.addQuery('preference_code', activities[i].preferences['default']);
  				gr.query();
  				var notification_preference;
  				if(gr.next())
  					notification_preference = gr.sys_id;
  				else{
  					//insert the tuple
  					gr.initialize();
  					gr.subscribable_object = prefData.sub_object.sys_id;
  					gr.activity_type = activities[i].activity_type_id;
  					gr.is_global = false;
  					gr.preference_code = activities[i].preferences['default'];
  					gr.insert();
  					notification_preference = gr.sys_id;
  				}
  				var subPrefRec = new GlideRecord(this.SUB_NOTIF_PREF);
  				if(prefMap[activities[i].activity_type_id]){
  					//Update existing record
  					subPrefRec.addQuery('subscription', prefMap.subscriptionId);
  					subPrefRec.addQuery('sys_id', prefMap[activities[i].activity_type_id].sys_id);
  					subPrefRec.query();
  					if(subPrefRec.next()){
  						subPrefRec.notification_preference = notification_preference + '';
  						subPrefRec.update();
  					}
  				}else{
  					//insert a new record for the user
  					subPrefRec.initialize();
  					subPrefRec.subscription = prefMap.subscriptionId;
  					subPrefRec.notification_preference = notification_preference;
  					subPrefRec.insert();
  				}
  				result.push({"activity_id": activities[i].activity_type_id + ''});
  			}
  		}
  	}
  	return result;
  },
  
  canFetchPreferences: function(profileId){
  	var hasRole = gs.hasRole('actsub_admin');
  	if (hasRole == false && pm.isActive('com.sn_communities')) {
  		return (gs.hasRole('snc_internal') || gs.hasRole('snc_external')) &&
  			gs.getUserID() == profileId;
  	}
  	return hasRole || (gs.getUserID() == profileId);
  },
  
  /*
  *Evaluates whether given activity is done after the user subscription.
  *Avoids fetching activities that happened before subscription
  @parameter - streamId: sys id of a activity stream
  @parameter - objectIds: list of subscribable object ids
  @parameter - activityTime: created time of the activity
  @return - true/false 
  */
  hasSubscribedBeforeActivityDate: function(streamId, objectIds, activityTime){
  	if(!streamId)
  		return false;
  	var objs = objectIds.join(',');
  	var subscriptionGr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	subscriptionGr.addQuery('sub_obj_id','IN',objs);
  	subscriptionGr.addQuery('sys_created_on', '<', activityTime);
  	subscriptionGr.addQuery('stream_id',streamId);
  	subscriptionGr.orderBy('sys_created_on');
  	subscriptionGr.setLimit(1);
  	subscriptionGr.query();
  	return subscriptionGr.hasNext();
  },
  
  /*
  * Get the users followed by the given profileId
  @parameter - profileId: live profile id of the user
  @return - list of userids and profile ids of users followed by the user
  */
  getFollowedUsersByProfile: function(profileId){
  	var subscriptionGr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	subscriptionGr.addQuery('subscriber_id', profileId);
  	subscriptionGr.addQuery('sub_obj_name', 'live_profile');
  	subscriptionGr.query();
  	var followingUsers = [];
  	while(subscriptionGr.next()){
  		followingUsers.push(subscriptionGr.sub_obj_id + '');
  	}
  	return followingUsers;
  },
  
  getSubscriptionsForStream: function(streamId){
  	if(!streamId)
  		return '';
  	var gr = new GlideRecord(this.SUBSCRIPTIONS_TABLE);
  	gr.addQuery('stream_id', streamId);
  	gr.query();
  	var result = [];
  	while(gr.next()){
  		if(this.activitySubContext.isCommunityPluginActive == true
  			&& gr.sub_obj_id.content && !gr.sub_obj_id.content.active)
  			continue;
  		result.push(gr.sub_obj_id.toString());
  	}
  	return result;
  },
  
  type: 'SubscriptionDAO'
};

Sys ID

5aa98f87db003200fa9b32d8f0b8f5ef

Offical Documentation

Official Docs: