NodeBB/NodeBB

View on GitHub
src/user/follow.js

Summary

Maintainability
A
3 hrs
Test Coverage

'use strict';

const plugins = require('../plugins');
const db = require('../database');

module.exports = function (User) {
    User.follow = async function (uid, followuid) {
        await toggleFollow('follow', uid, followuid);
    };

    User.unfollow = async function (uid, unfollowuid) {
        await toggleFollow('unfollow', uid, unfollowuid);
    };

    async function toggleFollow(type, uid, theiruid) {
        if (parseInt(uid, 10) <= 0 || parseInt(theiruid, 10) <= 0) {
            throw new Error('[[error:invalid-uid]]');
        }

        if (parseInt(uid, 10) === parseInt(theiruid, 10)) {
            throw new Error('[[error:you-cant-follow-yourself]]');
        }
        const [exists, isFollowing] = await Promise.all([
            User.exists(theiruid),
            User.isFollowing(uid, theiruid),
        ]);
        if (!exists) {
            throw new Error('[[error:no-user]]');
        }

        await plugins.hooks.fire('filter:user.toggleFollow', {
            type,
            uid,
            theiruid,
            isFollowing,
        });

        if (type === 'follow') {
            if (isFollowing) {
                throw new Error('[[error:already-following]]');
            }
            const now = Date.now();
            await db.sortedSetAddBulk([
                [`following:${uid}`, now, theiruid],
                [`followers:${theiruid}`, now, uid],
            ]);
        } else {
            if (!isFollowing) {
                throw new Error('[[error:not-following]]');
            }
            await db.sortedSetRemoveBulk([
                [`following:${uid}`, theiruid],
                [`followers:${theiruid}`, uid],
            ]);
        }

        const [followingCount, followerCount] = await Promise.all([
            db.sortedSetCard(`following:${uid}`),
            db.sortedSetCard(`followers:${theiruid}`),
        ]);
        await Promise.all([
            User.setUserField(uid, 'followingCount', followingCount),
            User.setUserField(theiruid, 'followerCount', followerCount),
        ]);
    }

    User.getFollowing = async function (uid, start, stop) {
        return await getFollow(uid, 'following', start, stop);
    };

    User.getFollowers = async function (uid, start, stop) {
        return await getFollow(uid, 'followers', start, stop);
    };

    async function getFollow(uid, type, start, stop) {
        if (parseInt(uid, 10) <= 0) {
            return [];
        }
        const uids = await db.getSortedSetRevRange(`${type}:${uid}`, start, stop);
        const data = await plugins.hooks.fire(`filter:user.${type}`, {
            uids: uids,
            uid: uid,
            start: start,
            stop: stop,
        });
        return await User.getUsers(data.uids, uid);
    }

    User.isFollowing = async function (uid, theirid) {
        if (parseInt(uid, 10) <= 0 || parseInt(theirid, 10) <= 0) {
            return false;
        }
        return await db.isSortedSetMember(`following:${uid}`, theirid);
    };
};