NotificationService.java 15.5 KB
package com.tanpu.community.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tanpu.common.api.CommonResp;
import com.tanpu.common.exception.BizException;
import com.tanpu.common.util.JsonUtil;
import com.tanpu.common.uuid.UuidGenHelper;
import com.tanpu.community.api.beans.vo.feign.fatools.UserInfoResp;
import com.tanpu.community.api.constants.RedisKeyConstant;
import com.tanpu.community.api.enums.DeleteTagEnum;
import com.tanpu.community.api.enums.NotificationTypeEnum;
import com.tanpu.community.cache.RedisCache;
import com.tanpu.community.dao.entity.NotificationForwardDO;
import com.tanpu.community.dao.entity.NotificationLikeDO;
import com.tanpu.community.dao.entity.community.NotificationEntity;
import com.tanpu.community.dao.mapper.community.NotificationMapper;
import com.tanpu.community.feign.fatools.FeignClientForFatools;
import com.tanpu.community.util.TimeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

@Service
public class NotificationService {

    @Resource
    private NotificationMapper notificationMapper;

    @Autowired
    private UuidGenHelper uuidGenHelper;

    @Autowired
    private FeignClientForFatools feignClientForFatools;


    @Autowired
    private RedisCache redisCache;


    public void insert(String operatorId, String notifierId, NotificationTypeEnum type, String targetId, String content) {
        NotificationEntity entity = NotificationEntity.builder().operatorId(operatorId)
                .notificationId(uuidGenHelper.getUuidStr())
                .notifiedUserId(notifierId)
                .messageType(type.getCode())
                .content(content)
                .operatorId(operatorId)
                .targetId(targetId)
                .build();
        insert(entity);
    }

    public void insert(String operatorId, String notifierId, NotificationTypeEnum type, String targetId, String content
            , LocalDateTime createTime) {
        NotificationEntity entity = NotificationEntity.builder().operatorId(operatorId)
                .notificationId(uuidGenHelper.getUuidStr())
                .notifiedUserId(notifierId)
                .messageType(type.getCode())
                .content(content)
                .operatorId(operatorId)
                .targetId(targetId)
                .createTime(createTime)
                .updateTime(createTime)
                .build();
        insert(entity);
    }


    public void insertForward(String operatorId, String notifierId, String forwardThemeId, String topicId, String text, String themeId) {
        NotificationForwardDO forwardDO = NotificationForwardDO.builder().topicId(topicId).content(text).themeId(themeId).build();
        NotificationEntity entity = NotificationEntity.builder().operatorId(operatorId)
                .notificationId(uuidGenHelper.getUuidStr())
                .notifiedUserId(notifierId)
                .messageType(NotificationTypeEnum.FORWARD.getCode())
                .content(JsonUtil.toJson(forwardDO))
                .operatorId(operatorId)
                .targetId(forwardThemeId)
                .build();
        insert(entity);

    }

    @Transactional
    public void insertLike(String operatorId, String notifierId, String targetId) {
        NotificationEntity entity = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getMessageType, NotificationTypeEnum.LIKE.getCode())
                .eq(NotificationEntity::getTargetId, targetId)
                .eq(NotificationEntity::getNotifiedUserId, notifierId));
        if (entity != null) {
            NotificationLikeDO notificationLikeDO = JsonUtil.toBean(entity.getContent(), NotificationLikeDO.class);
            notificationLikeDO.addItem(operatorId);
            entity.setContent(JsonUtil.toJson(notificationLikeDO));
            entity.setUpdateTime(LocalDateTime.now());
            notificationMapper.updateById(entity);
        } else {
            NotificationLikeDO notificationLikeDO = new NotificationLikeDO();
            notificationLikeDO.addItem(operatorId);
            NotificationEntity build = NotificationEntity.builder().operatorId(operatorId)
                    .notificationId(uuidGenHelper.getUuidStr())
                    .messageType(NotificationTypeEnum.LIKE.getCode())
                    .notifiedUserId(notifierId)
                    .content(JsonUtil.toJson(notificationLikeDO))
                    .targetId(targetId)
                    .operatorId(operatorId)
                    .build();
            insert(build);
        }

    }

    @Transactional
    public void insertLikeComment(String operatorId, String notifierId, String targetId) {
        NotificationEntity entity = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getMessageType, NotificationTypeEnum.COMMENT_LIKE.getCode())
                .eq(NotificationEntity::getTargetId, targetId)
                .eq(NotificationEntity::getNotifiedUserId, notifierId));
        if (entity != null) {
            NotificationLikeDO notificationLikeDO = JsonUtil.toBean(entity.getContent(), NotificationLikeDO.class);
            notificationLikeDO.addItem(operatorId);
            entity.setContent(JsonUtil.toJson(notificationLikeDO));
            entity.setUpdateTime(LocalDateTime.now());
            notificationMapper.updateById(entity);
        } else {
            NotificationLikeDO notificationLikeDO = new NotificationLikeDO();
            notificationLikeDO.addItem(operatorId);
            NotificationEntity build = NotificationEntity.builder().operatorId(operatorId)
                    .notificationId(uuidGenHelper.getUuidStr())
                    .messageType(NotificationTypeEnum.COMMENT_LIKE.getCode())
                    .notifiedUserId(notifierId)
                    .content(JsonUtil.toJson(notificationLikeDO))
                    .targetId(targetId)
                    .operatorId(operatorId)
                    .build();
            insert(build);
        }

    }

    @Transactional
    public void insert(NotificationEntity entity) {
        notificationMapper.insert(entity);
    }


    public NotificationEntity queryById(String notificationId) {
        return notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getNotificationId, notificationId));
    }


    public List<NotificationEntity> query(String userId, Integer type, String lastId, Integer pageSize) {
        LambdaQueryWrapper<NotificationEntity> queryWrapper = new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getNotifiedUserId, userId)
                .orderByDesc(NotificationEntity::getUpdateTime)
                .last("limit " + pageSize);


        if (StringUtils.isNotBlank(lastId)) {
            NotificationEntity lastOne = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                    .eq(NotificationEntity::getNotificationId, lastId));
            queryWrapper.lt(NotificationEntity::getUpdateTime, lastOne.getCreateTime());
        }
        if (!NotificationTypeEnum.ALL.getCode().equals(type) && !NotificationTypeEnum.LIKE.getCode().equals(type)) {
            queryWrapper.eq(NotificationEntity::getMessageType, type);
        } else if (NotificationTypeEnum.LIKE.getCode().equals(type)) {
            // 类型2点赞返回评论点赞和主题点赞
            queryWrapper.in(NotificationEntity::getMessageType,
                    Arrays.asList(NotificationTypeEnum.LIKE.getCode(), NotificationTypeEnum.COMMENT_LIKE.getCode()));
        }
        return notificationMapper.selectList(queryWrapper);
    }


    public void truncate() {
        notificationMapper.delete(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode()));
    }

    public void insertLike(String operatorId, String notifierId, String targetId, LocalDateTime updateTime) {
        NotificationEntity entity = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getMessageType, NotificationTypeEnum.LIKE.getCode())
                .eq(NotificationEntity::getTargetId, targetId)
                .eq(NotificationEntity::getNotifiedUserId, notifierId));
        if (entity != null) {
            NotificationLikeDO notificationLikeDO = JsonUtil.toBean(entity.getContent(), NotificationLikeDO.class);
            notificationLikeDO.addItem(operatorId);

            entity.setContent(JsonUtil.toJson(notificationLikeDO));
            entity.setUpdateTime(updateTime);
            notificationMapper.updateById(entity);
        } else {
            NotificationLikeDO notificationLikeDO = new NotificationLikeDO();
            notificationLikeDO.addItem(operatorId);
            NotificationEntity build = NotificationEntity.builder().operatorId(operatorId)
                    .notificationId(uuidGenHelper.getUuidStr())
                    .messageType(NotificationTypeEnum.LIKE.getCode())
                    .notifiedUserId(notifierId)
                    .content(JsonUtil.toJson(notificationLikeDO))
                    .targetId(targetId)
                    .operatorId(operatorId)
                    .createTime(updateTime)
                    .updateTime(updateTime)
                    .build();
            insert(build);
        }

    }

    // 消息通知队列缓存
    public void putNotifyCache(String notifyUserId, String operatorId, NotificationTypeEnum type) {
        UserInfoResp userInfo = getUserInfo(operatorId);
        redisCache.incr(RedisKeyConstant.MESSAGE_NOTIFY_COUNT + notifyUserId);
        redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_TIME + notifyUserId, TimeUtils.format(LocalDateTime.now()), 60 * 60 * 24 * 30);
        if (NotificationTypeEnum.COMMENT_LIKE.equals(type)) {
            redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + "点赞了你的评论", 60 * 60 * 24 * 30);
        } else if (NotificationTypeEnum.FOLLOW.equals(type)) {
            redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + "关注了你", 60 * 60 * 24 * 30);
        } else {
            redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + type.getType() + "了你的内容", 60 * 60 * 24 * 30);
        }
    }


    // 删除评论通知及缓存,并更新
    public void deleteCommentNotify(String notifyUserId, String operatorId, String commentId, LocalDateTime commentTime) {
        // 物理删除
        NotificationEntity commentNotify = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>()
                .eq(NotificationEntity::getTargetId, commentId)
                .eq(NotificationEntity::getOperatorId, operatorId)
                .eq(NotificationEntity::getNotifiedUserId, notifyUserId)
                .eq(NotificationEntity::getMessageType, NotificationTypeEnum.COMMENT.getCode()));
        NotificationEntity last = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>().eq(NotificationEntity::getNotifiedUserId, notifyUserId)
                .orderByDesc(NotificationEntity::getUpdateTime)
                .last("limit 1"));
        if (commentNotify==null || last==null){
            return;
        }
        notificationMapper.deleteById(commentNotify.getId());
        // 如果删除的评论是最後一條通知,则需要从库中再找一条最新的
        if (last.getNotificationId().equals(commentNotify.getNotificationId())) {
            last = notificationMapper.selectOne(new LambdaQueryWrapper<NotificationEntity>().eq(NotificationEntity::getNotifiedUserId, notifyUserId)
                    .orderByDesc(NotificationEntity::getUpdateTime)
                    .last("limit 1"));
            if (last == null) {
                // 没有其他通知,置空
                redisCache.evict(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId);
                redisCache.evict(RedisKeyConstant.MESSAGE_NOTIFY_LAST_TIME + notifyUserId);

            } else {
                // 有通知
                UserInfoResp userInfo = getUserInfo(last.getOperatorId());
                redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_TIME + notifyUserId, TimeUtils.format(last.getUpdateTime()), 60 * 60 * 24 * 30);
                if (NotificationTypeEnum.FOLLOW.getCode().equals(last.getMessageType())) {
                    redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + "关注了你", 60 * 60 * 24 * 30);
                } else {
                    redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId
                            , userInfo.getNickName() + NotificationTypeEnum.lookup(last.getMessageType()) + "了你的内容"
                            , 60 * 60 * 24 * 30);
                }
            }
        }

        // 处理更新数量
        String lastTime = redisCache.get(RedisKeyConstant.MESSAGE_NOTIFY_QUERY_TIME + notifyUserId);
        LocalDateTime lastQueryTime = StringUtils.isNotBlank(lastTime) ? JsonUtil.toBean(lastTime, LocalDateTime.class) : LocalDateTime.now();
        // 如果删除的评论时时间在红点提示时间内,则缓存数-1
        if (StringUtils.isBlank(lastTime) || TimeUtils.lessThan(lastQueryTime, commentTime)) {
            redisCache.decr(RedisKeyConstant.MESSAGE_NOTIFY_COUNT + notifyUserId);
        }
    }


    // init用
    public void putNotifyCache(String notifyUserId, String operatorId, NotificationTypeEnum type, LocalDateTime updateTime) {
        UserInfoResp userInfo = getUserInfo(operatorId);
        redisCache.incr(RedisKeyConstant.MESSAGE_NOTIFY_COUNT + notifyUserId);
        String cacheTime = redisCache.get(RedisKeyConstant.MESSAGE_NOTIFY_LAST_TIME + notifyUserId);
        if (StringUtils.isBlank(cacheTime) || TimeUtils.lessThan(cacheTime, updateTime)) {
            redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + type.getType() + "了你的内容", 60 * 60 * 24 * 30);
            redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_TIME + notifyUserId, TimeUtils.format(updateTime), 60 * 60 * 24 * 30);
        }
    }

    // init用
    public void putNotifyCacheFollow(String notifyUserId, String operatorId, LocalDateTime updateTime) {
        UserInfoResp userInfo = getUserInfo(operatorId);
        redisCache.incr(RedisKeyConstant.MESSAGE_NOTIFY_COUNT + notifyUserId);
        String cacheTime = redisCache.get(RedisKeyConstant.MESSAGE_NOTIFY_LAST_TIME + notifyUserId);
        if (StringUtils.isBlank(cacheTime) || TimeUtils.lessThan(cacheTime, updateTime)) {
            redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_MSG + notifyUserId, userInfo.getNickName() + "关注了你", 60 * 60 * 24 * 30);
            redisCache.set(RedisKeyConstant.MESSAGE_NOTIFY_LAST_TIME + notifyUserId, TimeUtils.format(updateTime), 60 * 60 * 24 * 30);

        }
    }

    public void deleteComment(String commentId) {

    }


    private UserInfoResp getUserInfo(String authorId) {
        CommonResp<UserInfoResp> userInfoNewCommonResp = feignClientForFatools.queryUserInfoNew(authorId);
        if (userInfoNewCommonResp.isNotSuccess()) {
            throw new BizException("内部接口调用失败");
        }
        return userInfoNewCommonResp.getData();
    }
}