mini_subscribe_logic.go 11.3 KB
package message

import (
	"context"
	"fmt"
	"github.com/jinzhu/copier"
	"github.com/silenceper/wechat/v2"
	"github.com/silenceper/wechat/v2/cache"
	miniConfig "github.com/silenceper/wechat/v2/miniprogram/config"
	"github.com/silenceper/wechat/v2/miniprogram/subscribe"
	"github.com/zeromicro/go-zero/core/logx"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/db/transaction"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"
	"strings"
	"time"
)

type MiniSubscribeLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewMiniSubscribeLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniSubscribeLogic {
	return &MiniSubscribeLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *MiniSubscribeLogic) getSubScribe() *subscribe.Subscribe {
	miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
		AppID:     l.svcCtx.Config.Wechat.AppID,
		AppSecret: l.svcCtx.Config.Wechat.AppSecret,
		Cache:     cache.NewMemory(),
	})
	return miniprogram.GetSubscribe()
}

// getOpenId 获取绑定用户openID
func (l *MiniSubscribeLogic) getOpenId(conn transaction.Conn, userId int64) (string, error) {
	userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
	if err != nil {
		return "", err
	}
	//获取微信绑定
	userWechat, err := l.svcCtx.UserWechatRepository.FindOneByPhone(l.ctx, conn, userInfo.Phone)
	if err != nil {
		return "", err
	}
	return userWechat.OpenId, nil
}

// sendAndDecrease 保存并扣减订阅消息
func (l *MiniSubscribeLogic) sendAndDecrease(conn transaction.Conn, companyId, userId int64, mType int, msg *subscribe.Message) error {
	templateData := make(map[string]interface{})
	_ = copier.Copy(&templateData, msg.Data)
	subscribeMessage := &domain.MessageSubscribe{
		Type:         mType,
		CompanyId:    companyId,
		UserId:       userId,
		OpenId:       msg.ToUser,
		TemplateId:   msg.TemplateID,
		TemplateData: templateData,
	}
	//获取订阅次数
	userSubscribe, err := l.svcCtx.UserSubscribeRepository.FindOneByType(l.ctx, conn, companyId, userId, mType)
	if err != nil || userSubscribe.Count <= 0 {
		subscribeMessage.Result = "fail"
		subscribeMessage.Error = "订阅次数已用完"
	} else {
		//扣减订阅次数
		userSubscribe.Count = userSubscribe.Count - 1
		_, err = l.svcCtx.UserSubscribeRepository.Update(l.ctx, conn, userSubscribe)
		if err != nil {
			return err
		}
		//发送订阅消息
		subCtx := l.getSubScribe()
		sendErr := subCtx.Send(msg)
		if sendErr != nil {
			subscribeMessage.Result = "fail"
			subscribeMessage.Error = sendErr.Error()
		} else {
			subscribeMessage.Result = "ok"
		}
	}
	//保存订阅结果
	_, err = l.svcCtx.MessageSubscribeRepository.Insert(l.ctx, conn, subscribeMessage)
	if err != nil {
		return err
	}
	return nil
}

func (l *MiniSubscribeLogic) messageSubscribe(companyId, userId int64, mType int) *domain.MessageSubscribe {
	return &domain.MessageSubscribe{
		Type:      mType,
		CompanyId: companyId,
		UserId:    userId,
	}
}

// getReplyCommentUserInfo 获取评论消息用户信息 用户名称+职位 例:张三-董事办
func (l *MiniSubscribeLogic) getReplyCommentUserInfo(conn transaction.Conn, companyId, userId int64) (string, error) {
	userInfo, err := l.svcCtx.UserRepository.FindOne(l.ctx, conn, userId)
	if err != nil {
		return "", xerr.NewErrMsgErr("获取评论用户信息失败", err)
	}
	users := []string{userInfo.Name}
	if len(userInfo.Roles) > 0 {
		_, roles, err := l.svcCtx.RoleRepository.Find(l.ctx, conn, domain.IndexCompanyId(companyId)().MustWithKV("ids", userInfo.Roles))
		if err == nil && len(roles) > 0 {
			roleNames := make([]string, 0)
			for _, item := range roles {
				roleNames = append(roleNames, item.Name)
			}
			users = append(users, strings.Join(roleNames, "、"))
		}
	}
	return strings.Join(users, "-"), nil
}

// ReplyComment 发送评论订阅消息
// @param conn 数据库连接
// @param article 文章
// @param comment 评论
func (l *MiniSubscribeLogic) ReplyComment(conn transaction.Conn, article *domain.Article, comment *domain.ArticleComment) error {
	//评论用户+职位 例: 张三-董事办
	fromUserName, err := l.getReplyCommentUserInfo(conn, comment.CompanyId, comment.FromUserId)
	if err != nil {
		return xerr.NewErrMsgErr("发送消息失败", err)
	}
	//评论消息
	msg := &subscribe.Message{
		TemplateID: domain.SubscribeTemplateComment,
		Data: map[string]*subscribe.DataItem{
			//文章标题
			"thing1": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
			//评论内容
			"thing2": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
			//评论时间
			"time3": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
			//评论用户
			"thing5": &subscribe.DataItem{Value: fromUserName},
			//备注
			"thing9": &subscribe.DataItem{Value: ""},
		},
		MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
	}
	//发帖人接收消息
	openId, err := l.getOpenId(conn, article.AuthorId)
	//未绑定微信号,直接返回
	if err == nil && openId != "" {
		msg.ToUser = openId
		msg.Page = fmt.Sprintf("/pages/detail/more-comment?id=%v", article.Id) //跳转页面 帖子评论聚合页
		//备注
		userCount, err := l.svcCtx.ArticleCommentRepository.CommentUserCount(l.ctx, conn, comment.CompanyId, comment.ArticleId)
		msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的帖子最近已有%v人评论,点击查看详情", userCount)}
		//发送微信订阅消息
		err = l.sendAndDecrease(conn, comment.CompanyId, article.AuthorId, domain.SubscribeTypeReplyComment, msg)
		if err != nil {
			return xerr.NewErrMsgErr("评论失败", err)
		}
	}
	//评论回复
	if comment.Pid > 0 {
		toOpenId, err := l.getOpenId(conn, comment.ToUserId)
		if err == nil && toOpenId != "" {
			msg.ToUser = toOpenId
			msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面评论聚合页
			//备注
			replyCount, err := l.svcCtx.ArticleCommentRepository.ReplyUserCount(l.ctx, conn, comment.CompanyId, comment.Pid)
			if err == nil {
				msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("您的评论最近已有%v人回复,点击查看详情", replyCount)}
				//发送微信订阅消息
				err = l.sendAndDecrease(conn, comment.CompanyId, comment.ToUserId, domain.SubscribeTypeReplyComment, msg)
				if err != nil {
					return xerr.NewErrMsgErr("评论失败", err)
				}
			}
		}
	}
	//@消息
	if len(comment.AtWho) > 0 {
		for _, at := range comment.AtWho {
			atOpenId, err := l.getOpenId(conn, at.Id)
			//未绑定微信跳过
			if err != nil || atOpenId == "" {
				continue
			}
			msg.ToUser = atOpenId
			msg.Page = fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", article.Id, comment.Pid) //跳转页面 评论详情页
			//备注
			msg.Data["thing9"] = &subscribe.DataItem{Value: fmt.Sprintf("%v在评论中提到了你", comment.FromUser.Name)}
			//发送微信订阅消息
			err = l.sendAndDecrease(conn, comment.CompanyId, at.Id, domain.SubscribeTypeReplyComment, msg)
			if err != nil {
				return xerr.NewErrMsgErr("评论失败", err)
			}
		}
	}
	return nil
}

// LikeArticle 帖子点赞订阅消息
func (l *MiniSubscribeLogic) LikeArticle(conn transaction.Conn, article *domain.Article, userInfo *domain.User) error {
	openId, err := l.getOpenId(conn, article.AuthorId)
	if err != nil || openId == "" {
		return nil
	}
	newArticle, err := l.svcCtx.ArticleRepository.FindOne(l.ctx, conn, article.Id)
	if err != nil {
		return xerr.NewErrMsgErr("未获取到帖子信息", err)
	}
	msg := &subscribe.Message{
		ToUser:     openId,
		TemplateID: domain.SubscribeTemplateLike,
		Page:       fmt.Sprintf("/pages/detail/detail?id=%v", article.Id),
		Data: map[string]*subscribe.DataItem{
			//点赞用户
			"name1": &subscribe.DataItem{Value: userInfo.Name},
			//点赞时间
			"date2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
			//动态内容
			"thing8": &subscribe.DataItem{Value: article.GetSubscribeMessageTitle()},
			//被赞次数
			"number4": &subscribe.DataItem{Value: newArticle.CountLove},
			//温馨提示
			"thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
		},
		MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
	}
	err = l.sendAndDecrease(conn, article.CompanyId, article.AuthorId, domain.SubscribeTypeLike, msg)
	if err != nil {
		return xerr.NewErrMsgErr("点赞失败", err)
	}
	return nil
}

// LikeComment 点赞评论订阅消息
func (l *MiniSubscribeLogic) LikeComment(conn transaction.Conn, comment *domain.ArticleComment, userInfo *domain.User) error {
	openId, err := l.getOpenId(conn, comment.FromUserId)
	if err != nil || openId == "" {
		return nil
	}
	//获取被赞次数
	newComment, err := l.svcCtx.ArticleCommentRepository.FindOne(l.ctx, conn, comment.Id)
	if err != nil {
		return xerr.NewErrMsgErr("未获取到评论信息", err)
	}
	msg := &subscribe.Message{
		ToUser:     openId,
		TemplateID: domain.SubscribeTemplateLike,
		Page:       fmt.Sprintf("/pages/detail/reply-comment?id=%v&commentId=%v", comment.ArticleId, comment.Id),
		Data: map[string]*subscribe.DataItem{
			//点赞用户
			"name1": &subscribe.DataItem{Value: userInfo.Name},
			//点赞时间
			"date2": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
			//动态内容
			"thing8": &subscribe.DataItem{Value: comment.GetSubscribeMessageContent()},
			//被赞次数
			"number4": &subscribe.DataItem{Value: newComment.CountUserLove},
			//温馨提示
			"thing5": &subscribe.DataItem{Value: "这条内容很受欢迎哦,快来看看吧"},
		},
		MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
	}
	err = l.sendAndDecrease(conn, comment.CompanyId, comment.FromUserId, domain.SubscribeTypeLike, msg)
	if err != nil {
		return xerr.NewErrMsgErr("点赞失败", err)
	}
	return nil
}

// FollowArticle 发帖关注更新提醒
func (l *MiniSubscribeLogic) FollowArticle(conn transaction.Conn, article *domain.Article) error {
	//获取关注帖子作者的人员
	_, userInfo, err := l.svcCtx.UserFollowRepository.Find(l.ctx, conn, domain.NewQueryOptions().WithKV("toUserIds", []int64{article.AuthorId}))
	if err == nil && len(userInfo) > 0 {
		for _, item := range userInfo {
			openId, err := l.getOpenId(conn, item.FromUserId)
			if err != nil || openId == "" {
				continue
			}
			msg := &subscribe.Message{
				ToUser:     openId,
				TemplateID: domain.SubscribeTemplateFollow,
				Page:       fmt.Sprintf("/pages/detail/detail?id=%v", article.Id),
				Data: map[string]*subscribe.DataItem{
					//创作者
					"thing1": &subscribe.DataItem{Value: article.Author.Name},
					//作品名称
					"thing2": &subscribe.DataItem{Value: article.Title},
					//内容摘要
					"thing5": &subscribe.DataItem{Value: ""},
					//发布时间
					"time6": &subscribe.DataItem{Value: time.Now().Format("2006-01-02 15:04:05")},
					//温馨提示
					"thing3": &subscribe.DataItem{Value: "你关注的人发布了新的帖子"},
				},
				MiniprogramState: l.svcCtx.Config.Wechat.QrcodeEnv,
			}
			err = l.sendAndDecrease(conn, article.CompanyId, item.FromUserId, domain.SubscribeTypeFollow, msg)
			if err != nil {
				return xerr.NewErrMsgErr("保存订阅消息失败", err)
			}
		}
	}
	return nil
}