first commit

This commit is contained in:
2022-03-17 15:59:24 +08:00
commit 2b0debb847
592 changed files with 73946 additions and 0 deletions

150
service/group/CHANGELOG.md Normal file
View File

@@ -0,0 +1,150 @@
版本号`major.minor.patch`具体规则如下:
- major主版本号如有重大版本重构则该字段递增通常各主版本间接口不兼容。
- minor次版本号各次版本号间接口保持兼容如有接口新增或优化则该字段递增。
- patch补丁号如有功能改善或缺陷修复则该字段递增。
## version 2.3.0 2022_01_20
**Feature**
- 增加一堆 rpc 方法
- 关闭 http 服务
## version 2.2.0 2022_01_06
**Feature**
- [x] 批量加群 rpc 接口 v2.2.1
- [x] 批量退群 rpc 接口 v2.2.2
- [x] 交换群主 rpc 接口 v2.2.2
- 修改创群 RPC 接口 v2.2.3
## version 2.1.0 2021_12_23
**数据库变动**
- dtalk_group_info 增加 group_type 字段 (0: 普通群, 1: 全员群, 2: 部门群)
## version 2.0.6
**配置文件新增**
```toml
[Redis]
network = "tcp"
addr = "127.0.0.1:6379"
auth = ""
active = 60000
idle = 1024
dialTimeout = "200ms"
readTimeout = "500ms"
writeTimeout = "500ms"
idleTimeout = "120s"
expire = "30m"
```
**Feature**
- 实现退群 RPC 方法 2021_11_26_17_58_11
- 使用日志中间件记录请求, 日志设置 TraceId
- rpc log 增加 trace id 2021_12_06
- 所有方法增加 ctx
- 增加解散群 RPC 方法
- group 增加 cache 6 2021_12_07_15_37_50
## version 2.0.5 2021_11_05-
**数据库更新**
- group_name 修改长度
- dtalk_group_info 新增 group_aes_key 字段
- dtalk_group_info 新增 group_pub_name 字段
**Feature**
- 增加 aes 字段 v2.0.1 2021_11_05
- 增加 group_pub_name 字段 v2.0.2 2021_11_17
- 增加查询群信息 rpc 接口 v2.0.3 2021_11_18
- 增加 maintain 数据库名称 v2.0.4 2021_11_19
- 修复更新群名称重复发送通知的特性 v2.0.5 2021_11_23
## version 2.0 2021_11_03
**配置文件更新**
group.toml
所有 `[xxxRPCClient]` 增加 `RegAddrs = "127.0.0.1:2379"` 字段
- 重构 group 代码 v2.0.0 2021_11_03
## version 1.6
**Feature**
- 增加加群申请接口 v1.6.0 2021.10.9
- 增加查询群成员 rpc 接口 v1.6.1 2021.10.10
- 改用 imparse 中的 proto @v1.6.2 2021.10.14
## version 1.5
**Feature**
- 增加加群 rpc 接口 v1.5.0 2021.9.24
- 增加搜索群列表接口 v1.5.4 2021.9.26
**Bug fix**
- 修复签名过期 bug v1.5.1 2021.9.26
- 生成不重复的 groupMarkId v1.5.2 2021.9.26
- 优化 groupMarkId 生成方法 v1.5.3 2021.9.26
- 修复批量邀请群成员全失败的逻辑 v1.5.5 2021.9.27
- 修复创建群聊时群成员包含群主的产生的 bug v1.5.6 2021.9.27
- 修复成员主动退群后还能收到退群的通知 v1.5.7 2021.9.28
## version 1.4
**Feature**
- 增加查询群列表 rpc 接口 @v1.4.0 2021.9.2
- 增加直接加群的接口 @v1.4.1 2021.9.6
- 查询群公开信息接口返回用户在群里的信息 v1.4.2 2021.9.9
- 扫码加群走邀请加群通道 v1.4.3 2021.9.9
## version 1.3
**Feature**
- 增加创群 rpc 接口 @v1.3.0 2021.8.23
- 接口可以选择只传整形或者字符串类型 ID @v1.3.1 2021.8.26
## version 1.2
**Feature**
- 接口增加 string 类型 Id @v1.2.0 2021.8.20
## version 1.1 @2021.7.26
**Feature**
- 群人数上限和管理员数量上限可以通过配置文件配置 @v1.1.1 2021.7.7
- notice 从 answer 服务接入 @v1.1.2 2021.7.15
- change alert.from from groupId to personId @v1.1.3 2021.7.26
**Bug fix**
- 群主不能把自己设置为管理员 @v1.1.4 2021.8.17
## version 1.1.0 @2021.7.1
**Feature**
增加 Prometheus 的指标监控
- http_requests_total
- http_response_time_seconds
## version 1.0.0 @2021.6.30
group init, 实现第一批需求接口
## example x.x.x @yy.mm.dd
**Feature**
**Bug Fixes**
**Improvement**
**Breaking Change**

51
service/group/Makefile Normal file
View File

@@ -0,0 +1,51 @@
VERSION := $(shell echo $(shell cat cmd/main.go | grep "projectVersion =" | cut -d '=' -f2))
APP_NAME := group
BUILD_DIR := build
APP := ${BUILD_DIR}/${APP_NAME}_v${VERSION}
PKG_NAME := ${APP_NAME}_v${VERSION}
PKG := ${PKG_NAME}.tar.gz
.PHONY: clean build pkg
main_path = "main"
go_version = $(shell go version | awk '{ print $3 }')
build_time = $(shell date "+%Y-%m-%d %H:%M:%S %Z")
git_commit = $(shell git rev-parse --short=10 HEAD)
flags := -ldflags "-X '${main_path}.goVersion=${go_version}' \
-X '${main_path}.buildTime=${build_time}' \
-X '${main_path}.gitCommit=${git_commit}' \
-X 'google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn'"
clean: ## Remove previous build
@rm -rf ${BUILD_DIR}
@go clean
swag:
@echo '┌ start gen swag'
@swag init -g server/http/http.go
@echo '└ end gen swag'
build: swag #checkgofmt ## Build the binary file
@echo '┌ start build $(APP)'
@GOOS=linux GOARCH=amd64 GO111MODULE=on GOPROXY=https://goproxy.cn,direct GOSUMDB="sum.golang.google.cn" go build -v ${flags} -o $(APP) cmd/main.go
@echo '└ end build $(APP)'
pkg: build ## Package
mkdir -p ${PKG_NAME}/bin
mkdir -p ${PKG_NAME}/etc
cp ${APP} ${PKG_NAME}/bin/
cp config/$(APP_NAME).toml ${PKG_NAME}/etc/
tar zvcf ${PKG} ${PKG_NAME}
rm -rf ${PKG_NAME}
run: swag
@echo '┌ start run $(APP)'
@go run cmd/main.go -conf config/group.toml
@echo '└ end run $(APP)'
REMOTE_BIN_PATH := /opt/dtalk/srv/app/bin
upload: build
@echo '┌ start upload $(APP)'
@rsync -r $(APP) 107:$(REMOTE_BIN_PATH)
@ssh 107 "cd $(REMOTE_BIN_PATH) && chmod 777 $(PKG_NAME) && ln -sf $(PKG_NAME) $(APP_NAME) && supervisorctl restart $(APP_NAME)"
@echo '┌ start upload $(APP)'

79
service/group/README.md Normal file
View File

@@ -0,0 +1,79 @@
# group 群组服务
## TODO
- [ ] 删除service 中所有带 Svc 后缀的方法
- [ ] dao 层暴露的方法把 biz 对象作为方法参数, 而不是 db
## 目录结构
```
group
├── api
├── build
├── cmd
├── config
├── dao
├── docs
├── logic
│ └── http
├── model
│ ├── biz
│ ├── db
│ └── types
├── server
│ ├── grpc
│ └── http
└── service
```
### api
包含 grpc 的 `proto` , `*.pb.go`, `client` 文件
client 提供 rpc 客户端的创建方法, 相当于手动给 grpc 客户端包了一层
### build
make build 指令生成的二进制文件保存目录
### cmd
项目启动目录
包括资源的初始化, http 和 rpc 服务的启动
### config
配置文件描述目录
### dao
数据访问层
注入到 service 中, 暴露数据操作方法, 不区分是操作数据库还是操作缓存(比如获得群信息, service 不关心是从数据库中拿还是从缓存中拿).
如有需要,可以与业务逻辑服务分开,单独暴露 rpc 方法, 提供给多个业务服务,类似:
![](https://pic3.zhimg.com/80/v2-bf7456dbea800d3b7bc209ede853b7a6_720w.jpg)
### docs
http api swag 描述文件, 由 `make swag` 生成
可以删去, 以后统一由 gateway 服务管理
### logic
使用`service`中的各种方法编排业务逻辑, 包含参数校验, 权限判断
### model
包含各种用到的结构体与 const 值
- `biz` service 中一直使用的结构体
- `db` 数据库字段映射(可以移动到 dao 层)
- `types` http服务的请求与返回(可以不要,因为 http 请求都移动到 gateway 了)
### server
http 服务和 grpc 服务的启动路径, 仅绑定参数, 不做任何处理
服务中的各个方法与 logic 中的方法一一对应
### service
各种业务方法, 假定传入的参数都是正确,经过验证的, 不进行权限判断

220
service/group/api/client.go Normal file
View File

@@ -0,0 +1,220 @@
package group
import (
"context"
"fmt"
"time"
"gitlab.33.cn/chat/dtalk/pkg/naming"
xgrpc "gitlab.33.cn/chat/dtalk/pkg/net/grpc"
"google.golang.org/grpc"
"google.golang.org/grpc/resolver"
)
type Client struct {
conn *grpc.ClientConn
client GroupClient
}
func New(etcdAddr, schema, srvName string, dial time.Duration, opts ...grpc.DialOption) *Client {
rb := naming.NewResolver(etcdAddr, schema)
resolver.Register(rb)
addr := fmt.Sprintf("%s:///%s", schema, srvName) // "schema://[authority]/service"
fmt.Println("group rpc client call addr:", addr)
conn, err := xgrpc.NewGRPCConnWithOpts(addr, dial, opts...)
if err != nil {
panic(err)
}
return &Client{
conn: conn,
client: NewGroupClient(conn),
}
}
func (c *Client) GetGroupIds(ctx context.Context, memberId string) ([]int64, error) {
in := &GetGroupIdsRequest{
MemberId: memberId,
}
res, err := c.client.GetGroupIds(ctx, in)
if err != nil {
return nil, err
}
return res.GroupIds, nil
}
func (c *Client) CheckInGroup(ctx context.Context, memberId string, groupId int64) (bool, error) {
in := &CheckInGroupRequest{
MemberId: memberId,
GroupId: groupId,
}
res, err := c.client.CheckInGroup(ctx, in)
if err != nil {
return false, err
}
return res.IsOk, err
}
func (c *Client) GetMemberIds(ctx context.Context, groupId int64) ([]string, error) {
in := &GetMemberIdsRequest{
GroupId: groupId,
}
res, err := c.client.GetMemberIds(ctx, in)
if err != nil {
return nil, err
}
return res.MemberIds, err
}
func (c *Client) CheckMute(ctx context.Context, memberId string, groupId int64) (bool, error) {
in := &CheckMuteRequest{
MemberId: memberId,
GroupId: groupId,
}
res, err := c.client.CheckMute(ctx, in)
if err != nil {
return false, err
}
return res.IsOk, nil
}
type Group struct {
Id int64
Name string
Avatar string
}
func (c *Client) GetGroups(ctx context.Context, id string) ([]*Group, error) {
in := &GetGroupsReq{
Id: id,
}
res, err := c.client.GetGroups(ctx, in)
if err != nil {
return nil, err
}
groups := make([]*Group, len(res.Groups))
for i, group := range res.Groups {
groups[i] = &Group{
Id: group.Id,
Name: group.Name,
Avatar: group.Avatar,
}
}
return groups, nil
}
func (c *Client) GetMember(ctx context.Context, groupId int64, memberId string) (*GetMemberResp, error) {
in := &GetMemberReq{
MemberId: memberId,
GroupId: groupId,
}
res, err := c.client.GetMember(ctx, in)
if err != nil {
return nil, err
}
return res, nil
}
// ------------------ new proto client ----------------------------------
func (c *Client) ChangeOwner(ctx context.Context, req *ChangeOwnerReq) (*ChangeOwnerResp, error) {
client := NewGroupClient(c.conn)
return client.ChangeOwner(ctx, req)
}
func (c *Client) CreateGroup(ctx context.Context, req *CreateGroupReq) (*CreateGroupResp, error) {
client := NewGroupClient(c.conn)
return client.CreateGroup(ctx, req)
}
func (c *Client) GetGroupList(ctx context.Context, req *GetGroupListReq) (*GetGroupListResp, error) {
client := NewGroupClient(c.conn)
return client.GetGroupList(ctx, req)
}
func (c *Client) GetGroupMemberInfo(ctx context.Context, req *GetGroupMemberInfoReq) (*GetGroupMemberInfoResp, error) {
client := NewGroupClient(c.conn)
return client.GetGroupMemberInfo(ctx, req)
}
func (c *Client) GetGroupMemberList(ctx context.Context, req *GetGroupMemberListReq) (*GetGroupMemberListResp, error) {
client := NewGroupClient(c.conn)
return client.GetGroupMemberList(ctx, req)
}
func (c *Client) GetMuteList(ctx context.Context, req *GetMuteListReq) (*GetMuteListResp, error) {
client := NewGroupClient(c.conn)
return client.GetMuteList(ctx, req)
}
func (c *Client) GetPriGroupInfo(ctx context.Context, req *GetPriGroupInfoReq) (*GetPriGroupInfoResp, error) {
client := NewGroupClient(c.conn)
return client.GetPriGroupInfo(ctx, req)
}
func (c *Client) GetPubGroupInfo(ctx context.Context, req *GetPubGroupInfoReq) (*GetPubGroupInfoResp, error) {
client := NewGroupClient(c.conn)
return client.GetPubGroupInfo(ctx, req)
}
func (c *Client) GroupDisband(ctx context.Context, req *GroupDisbandReq) (*GroupDisbandResp, error) {
client := NewGroupClient(c.conn)
return client.GroupDisband(ctx, req)
}
func (c *Client) GroupExit(ctx context.Context, req *GroupExitReq) (*GroupExitResp, error) {
client := NewGroupClient(c.conn)
return client.GroupExit(ctx, req)
}
func (c *Client) GroupRemove(ctx context.Context, req *GroupRemoveReq) (*GroupRemoveResp, error) {
client := NewGroupClient(c.conn)
return client.GroupRemove(ctx, req)
}
func (c *Client) InviteGroupMembers(ctx context.Context, req *InviteGroupMembersReq) (*InviteGroupMembersResp, error) {
client := NewGroupClient(c.conn)
return client.InviteGroupMembers(ctx, req)
}
func (c *Client) SetAdmin(ctx context.Context, req *SetAdminReq) (*SetAdminResp, error) {
client := NewGroupClient(c.conn)
return client.SetAdmin(ctx, req)
}
func (c *Client) UpdateGroupAvatar(ctx context.Context, req *UpdateGroupAvatarReq) (*UpdateGroupAvatarResp, error) {
client := NewGroupClient(c.conn)
return client.UpdateGroupAvatar(ctx, req)
}
func (c *Client) UpdateGroupFriendType(ctx context.Context, req *UpdateGroupFriendTypeReq) (*UpdateGroupFriendTypeResp, error) {
client := NewGroupClient(c.conn)
return client.UpdateGroupFriendType(ctx, req)
}
func (c *Client) UpdateGroupJoinType(ctx context.Context, req *UpdateGroupJoinTypeReq) (*UpdateGroupJoinTypeResp, error) {
client := NewGroupClient(c.conn)
return client.UpdateGroupJoinType(ctx, req)
}
func (c *Client) UpdateGroupMemberMuteTime(ctx context.Context, req *UpdateGroupMemberMuteTimeReq) (*UpdateGroupMemberMuteTimeResp, error) {
client := NewGroupClient(c.conn)
return client.UpdateGroupMemberMuteTime(ctx, req)
}
func (c *Client) UpdateGroupMemberName(ctx context.Context, req *UpdateGroupMemberNameReq) (*UpdateGroupMemberNameResp, error) {
client := NewGroupClient(c.conn)
return client.UpdateGroupMemberName(ctx, req)
}
func (c *Client) UpdateGroupMuteType(ctx context.Context, req *UpdateGroupMuteTypeReq) (*UpdateGroupMuteTypeResp, error) {
client := NewGroupClient(c.conn)
return client.UpdateGroupMuteType(ctx, req)
}
func (c *Client) UpdateGroupName(ctx context.Context, req *UpdateGroupNameReq) (*UpdateGroupNameResp, error) {
client := NewGroupClient(c.conn)
return client.UpdateGroupName(ctx, req)
}

View File

@@ -0,0 +1,6 @@
#!/bin/sh
protoc -I. -I$GOPATH/src \
--go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
*.proto

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,519 @@
// protoc -I=. -I=$GOPATH/src --go_out=plugins=grpc:. *.proto
syntax = "proto3";
package dtalk.group;
option go_package = "gitlab.33.cn/chat/dtalk/service/group";
// 群状态
enum GroupStatus {
GROUP_STATUS_NORMAL = 0; // 正常
GROUP_STATUS_BLOCK = 1; // 封禁
GROUP_STATUS_DISBAND = 2 ;// 解散
}
// 群类型
enum GroupType {
GROUP_TYPE_NORMAL = 0; // 普通群
GROUP_TYPE_ENT = 1; // 全员群
GROUP_TYPE_DEP = 2; // 部门群
}
// 群内加群设置
enum GroupJoinType {
GROUP_JOIN_TYPE_ANY = 0; // 无需审批(默认)
GROUP_JOIN_TYPE_ADMIN = 1; // 禁止加群,群主和管理员邀请加群
GROUP_JOIN_TYPE_APPLY = 2; // 普通人邀请需要审批,群主和管理员直接加群
}
// 群内发言设置
enum GroupMuteType {
GROUP_MUTE_TYPE_ANY = 0; // 全员可发言
GROUP_MUTE_TYPE_ADMIN = 1; // 全员禁言(除群主和管理员)
}
// 群内加好友设置
enum GroupFriendType {
GROUP_FRIEND_TYPE_ALLOW = 0; // 群内可加好友
GROUP_FRIEND_TYPE_DENY = 1; // 群内禁止加好友
}
// 群成员类型
enum GroupMemberType {
GROUP_MEMBER_TYPE_NORMAL = 0; // 群员
GROUP_MEMBER_TYPE_ADMIN = 1; // 管理员
GROUP_MEMBER_TYPE_OWNER = 2; // 群主
GROUP_MEMBER_TYPE_OTHER = 10; // 退群
}
message GroupInfo {
int64 id = 1;
string name = 2;
string avatar = 3;
}
message GroupMemberInfo {
// 成员 id
string id = 1;
// 成员在群里的名字
string name = 2;
}
message GetGroupIdsRequest{
string member_id = 1;
}
message GetGroupIdsReply {
repeated int64 group_ids = 1;
}
message CheckInGroupRequest{
string member_id = 1;
int64 group_id = 2;
}
message CheckInGroupReply {
bool is_ok = 1;
}
message GetMemberIdsRequest{
int64 group_id = 1;
}
message GetMemberIdsReply{
repeated string member_ids = 1;
}
message CheckMuteRequest {
string member_id = 1;
int64 group_id = 2;
}
message CheckMuteReply {
bool is_ok = 1;
}
// 得到加入的所有群
message GetGroupsReq {
string id = 1;
}
message GetGroupsResp {
repeated GroupInfo groups = 1;
}
// ---------------- ----------------------
message GroupBizInfo {
int64 id = 1;
string mark_id = 2;
string name = 3;
string avatar = 4;
int32 member_num = 5;
int32 member_maximum = 6;
string introduce = 7;
// 群状态0=正常 1=封禁 2=解散
GroupStatus status = 8;
string owner_id = 9;
int64 create_time = 10;
int64 update_time = 11;
// 加群方式0=无需审批默认1=禁止加群,群主和管理员邀请加群, 2=普通人邀请需要审批,群主和管理员直接加群
GroupJoinType join_type = 12;
// 禁言, 0=全员可发言, 1=全员禁言(除群主和管理员)
GroupMuteType mute_type = 13;
// 加好友限制, 0=群内可加好友1=群内禁止加好友
GroupFriendType friend_type = 14;
// 群内当前被禁言的人数
int32 mute_num = 15;
// 群内管理员数量
int32 admin_num = 16;
string AES_key = 17;
string pub_name = 18;
// 群类型 (0: 普通群, 1: 全员群, 2: 部门群)
GroupType type = 19;
GroupMemberBizInfo owner = 20;
GroupMemberBizInfo person = 21;
repeated GroupMemberBizInfo members = 22;
}
message GroupMemberBizInfo {
int64 group_id = 1;
string id = 2;
string name = 3;
// 用户角色0=群员,1=管理员, 2=群主10=退群
GroupMemberType type = 4;
// 该用户被禁言结束的时间 9223372036854775807=永久禁言
int64 mute_time = 5;
int64 join_time = 6;
}
// 创建群聊
message CreateGroupReq {
string name = 1;
GroupType group_type = 2;
GroupMemberInfo owner = 3;
repeated GroupMemberInfo members = 4;
}
message CreateGroupResp {
int64 group_id = 1;
}
message InviteGroupMembersReq {
int64 group_id = 1;
string inviter_id = 2;
repeated string member_ids = 3;
}
message InviteGroupMembersResp {
}
message GroupExitReq {
int64 group_id = 1;
string person_id = 2;
}
message GroupExitResp {
}
message GroupDisbandReq {
int64 group_id = 1;
string person_id = 2;
}
message GroupDisbandResp {
}
message GroupRemoveReq {
int64 group_id = 1;
string person_id = 2;
repeated string member_ids = 3;
}
message GroupRemoveResp {
// 群当前人数
int32 member_num = 1;
// 成功被踢的成员列表
repeated string member_ids = 2;
}
message ChangeOwnerReq {
int64 group_id = 1;
string person_id = 2;
// 被转让为群主的群成员 id
string member_id = 3;
}
message ChangeOwnerResp {
}
message UpdateGroupNameReq {
int64 group_id = 1;
string person_id = 2;
string name = 3;
string public_name = 4;
}
message UpdateGroupNameResp {
}
message UpdateGroupAvatarReq {
int64 group_id = 1;
string person_id = 2;
// 群头像 url
string avatar = 3;
}
message UpdateGroupAvatarResp {
}
message UpdateGroupJoinTypeReq {
int64 group_id = 1;
string person_id = 2;
GroupJoinType group_join_type = 3;
}
message UpdateGroupJoinTypeResp {
}
message UpdateGroupFriendTypeReq {
int64 group_id = 1;
string person_id = 2;
GroupFriendType group_friend_type = 3;
}
message UpdateGroupFriendTypeResp {
}
message UpdateGroupMuteTypeReq {
int64 group_id = 1;
string person_id = 2;
GroupMuteType group_mute_type = 3;
}
message UpdateGroupMuteTypeResp {
}
message UpdateGroupMemberNameReq {
int64 group_id = 1;
string person_id = 2;
string member_name = 3;
}
message UpdateGroupMemberNameResp {
}
message SetAdminReq {
int64 group_id = 1;
string person_id = 2;
string member_id = 3;
GroupMemberType group_member_type = 4;
}
message SetAdminResp {
}
message UpdateGroupMemberMuteTimeReq {
int64 group_id = 1;
string person_id = 2;
repeated string member_ids = 3;
int64 mute_time = 4;
}
message UpdateGroupMemberMuteTimeResp {
repeated GroupMemberBizInfo members = 1;
}
message GetPriGroupInfoReq {
int64 group_id = 1;
string person_id = 2;
int32 display_num = 3;
}
message GetPriGroupInfoResp {
GroupBizInfo group = 1;
}
message GetPubGroupInfoReq {
int64 group_id = 1;
string person_id = 2;
}
message GetPubGroupInfoResp {
GroupBizInfo group = 1;
}
message GetGroupListReq {
string person_id = 1;
}
message GetGroupListResp {
repeated GroupBizInfo groups = 1;
}
message GetGroupMemberListReq {
int64 group_id = 1;
string person_id = 2;
}
message GetGroupMemberListResp {
repeated GroupMemberBizInfo members = 1;
}
message GetGroupMemberInfoReq {
int64 group_id = 1;
string person_id = 2;
string member_id = 3;
}
message GetGroupMemberInfoResp {
GroupMemberBizInfo member = 1;
}
message GetMuteListReq {
int64 group_id = 1;
string person_id = 2;
}
message GetMuteListResp {
repeated GroupMemberBizInfo members = 1;
}
// -------------- oa 远程调用 ----------------
message ForceAddMemberReq{
string member_id = 1;
int64 group_id = 2;
}
message ForceAddMemberResp{
}
message ForceAddMembersReq {
int64 group_id = 1;
repeated GroupMemberInfo members = 2;
}
message ForceAddMembersResp{
}
message ForceDeleteMemberReq{
string member_id = 1;
int64 group_id = 2;
}
message ForceDeleteMemberResp{
}
message ForceDeleteMembersReq{
int64 group_id = 1;
repeated string member_ids = 2;
}
message ForceDeleteMembersResp{
}
message GetMemberReq{
string member_id = 1;
int64 group_id = 2;
}
message GetMemberResp{
int64 groupId = 1;
string groupMemberId = 2;
string groupMemberName = 3;
int32 groupMemberType = 4;
int64 groupMemberJoinTime = 5;
int64 groupMemberUpdateTime = 6;
}
message GetGroupInfoReq {
int64 groupId = 1;
}
message GetGroupInfoResp {
int64 groupId = 1;
bool group_exist = 2;
string group_name = 3;
string group_avatar = 4;
string group_owner_id = 5;
}
message ForceDisbandGroupReq {
int64 group_id = 1;
string ope_id = 2;
}
message ForceDisbandGroupResp {
}
message ForceUpdateGroupTypeReq {
int64 group_id = 1;
int32 group_type = 2;
}
message ForceUpdateGroupTypeResp {
int64 group_id = 1;
int32 group_type = 2;
}
message ForceJoinGroupsReq {
GroupMemberInfo member = 1;
repeated int64 group_ids = 2;
}
message ForceJoinGroupsResp {
}
message ForceExitGroupsReq {
GroupMemberInfo member = 1;
repeated int64 group_ids = 2;
}
message ForceExitGroupsResp {
}
message ForceChangeOwnerReq {
int64 group_id = 1;
GroupMemberInfo member = 2;
}
message ForceChangeOwnerResp {}
service Group {
rpc GetGroupIds(GetGroupIdsRequest) returns (GetGroupIdsReply);
rpc CheckInGroup(CheckInGroupRequest) returns (CheckInGroupReply);
rpc GetMemberIds(GetMemberIdsRequest) returns (GetMemberIdsReply);
rpc CheckMute(CheckMuteRequest) returns (CheckMuteReply);
// 得到加入的所有群
rpc GetGroups(GetGroupsReq) returns (GetGroupsResp);
// 查询成员
rpc GetMember(GetMemberReq) returns (GetMemberResp);
// 查询群信息
rpc GetGroupInfo(GetGroupInfoReq) returns (GetGroupInfoResp);
// ------------- gateway -----------
// 创建群聊
rpc CreateGroup(CreateGroupReq) returns (CreateGroupResp);
// 邀请新成员
rpc InviteGroupMembers(InviteGroupMembersReq) returns (InviteGroupMembersResp);
// 退出群
rpc GroupExit(GroupExitReq) returns (GroupExitResp);
// 解散群
rpc GroupDisband(GroupDisbandReq) returns (GroupDisbandResp);
// 踢人
rpc GroupRemove(GroupRemoveReq) returns (GroupRemoveResp);
// 转让群主
rpc ChangeOwner(ChangeOwnerReq) returns (ChangeOwnerResp);
// 更新群名称
rpc UpdateGroupName(UpdateGroupNameReq) returns(UpdateGroupNameResp);
// 更新群头像
rpc UpdateGroupAvatar(UpdateGroupAvatarReq) returns (UpdateGroupAvatarResp);
// 更新加群设置
rpc UpdateGroupJoinType(UpdateGroupJoinTypeReq) returns (UpdateGroupJoinTypeResp);
// 更新群内加好友设置
rpc UpdateGroupFriendType(UpdateGroupFriendTypeReq) returns (UpdateGroupFriendTypeResp);
// 更新群内禁言设置
rpc UpdateGroupMuteType(UpdateGroupMuteTypeReq) returns (UpdateGroupMuteTypeResp);
// 更新群内昵称
rpc UpdateGroupMemberName(UpdateGroupMemberNameReq) returns (UpdateGroupMemberNameResp);
// 设置群管理员
rpc SetAdmin(SetAdminReq) returns(SetAdminResp);
// 设置群成员禁言时间
rpc UpdateGroupMemberMuteTime(UpdateGroupMemberMuteTimeReq) returns(UpdateGroupMemberMuteTimeResp);
// 查询完整群信息
rpc GetPriGroupInfo(GetPriGroupInfoReq) returns(GetPriGroupInfoResp);
// 查询群公开信息
rpc GetPubGroupInfo(GetPubGroupInfoReq) returns (GetPubGroupInfoResp);
// 查询加入的群列表
rpc GetGroupList(GetGroupListReq) returns (GetGroupListResp);
// 查询群成员列表
rpc GetGroupMemberList(GetGroupMemberListReq) returns (GetGroupMemberListResp);
// 查询群成员信息
rpc GetGroupMemberInfo(GetGroupMemberInfoReq) returns (GetGroupMemberInfoResp);
// 查询群内禁言列表
rpc GetMuteList(GetMuteListReq) returns (GetMuteListResp);
// ------------- Third Force --------------
// 更新群类型
rpc ForceUpdateGroupType(ForceUpdateGroupTypeReq) returns(ForceUpdateGroupTypeResp);
// 解散群, 强制解散
rpc ForceDisbandGroup(ForceDisbandGroupReq) returns (ForceDisbandGroupResp);
// 添加成员
rpc ForceAddMember(ForceAddMemberReq) returns (ForceAddMemberResp);
// 批量添加成员
rpc ForceAddMembers(ForceAddMembersReq) returns (ForceAddMembersResp);
// 删除成员
rpc ForceDeleteMember(ForceDeleteMemberReq) returns (ForceDeleteMemberResp);
// 批量删除成员
rpc ForceDeleteMembers(ForceDeleteMembersReq) returns (ForceDeleteMembersResp);
// 一个人加入多个群
rpc ForceJoinGroups(ForceJoinGroupsReq) returns(ForceJoinGroupsResp);
// 一个人退出多个群
rpc ForceExitGroups(ForceExitGroupsReq) returns(ForceExitGroupsResp);
// 成为群主
rpc ForceChangeOwner(ForceChangeOwnerReq) returns(ForceChangeOwnerResp);
}

File diff suppressed because it is too large Load Diff

120
service/group/cmd/main.go Normal file
View File

@@ -0,0 +1,120 @@
package main
import (
"context"
"flag"
"fmt"
"net"
"os"
"os/signal"
"syscall"
"time"
"gitlab.33.cn/chat/dtalk/pkg/logger"
"github.com/Terry-Mao/goim/pkg/ip"
"gitlab.33.cn/chat/dtalk/pkg/naming"
"gitlab.33.cn/chat/dtalk/service/group/config"
"gitlab.33.cn/chat/dtalk/service/group/server/grpc"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
const srvName = "group"
var (
// projectVersion 项目版本
projectVersion = "2.3.1"
// goVersion go版本
goVersion = ""
// gitCommit git提交commit id
gitCommit = ""
// buildTime 编译时间
buildTime = ""
isShowVersion = flag.Bool("v", false, "show project version")
isMaintain = flag.Bool("maintain", false, "maintain data base")
)
// showVersion 显示项目版本信息
func showVersion(isShow bool) {
if isShow {
fmt.Printf("Project: %s\n", srvName)
fmt.Printf(" Version: %s\n", projectVersion)
fmt.Printf(" Go Version: %s\n", goVersion)
fmt.Printf(" Git Commit: %s\n", gitCommit)
fmt.Printf(" Build Time: %s\n", buildTime)
os.Exit(0)
}
}
func maintain(isMaintain bool, svc *service.Service) {
if isMaintain {
//err := svc.MaintainGroupAESKey()
//if err != nil {
// panic(err)
//}
os.Exit(0)
}
}
func main() {
flag.Parse()
showVersion(*isShowVersion)
if err := config.Init(); err != nil {
panic(err)
}
//log init
log := logger.New(config.Conf.Env, srvName)
log.Info().Interface("Config", config.Conf).
Msg("config info")
// service init
svc := service.New(config.Conf)
maintain(*isMaintain, svc)
//
//httpSrv := http.Init(svc)
// rpc init
rpc := grpc.New(config.Conf.GRPCServer, svc)
// register server
_, port, _ := net.SplitHostPort(config.Conf.GRPCServer.Addr)
addr := fmt.Sprintf("%s:%s", ip.InternalIP(), port)
if err := naming.Register(config.Conf.Reg.RegAddrs, config.Conf.Reg.SrvName, addr, config.Conf.Reg.Schema, 15); err != nil {
panic(err)
}
fmt.Println("register ok")
// init signal
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info().Str("signal", s.String()).Msg("service get a signal")
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
// 退出时从 etcd 中删除
if err := naming.UnRegister(config.Conf.Reg.SrvName, addr, config.Conf.Reg.Schema); err != nil {
log.Error().Err(err).Msg("naming.UnRegister")
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
//if err := httpSrv.Shutdown(ctx); err != nil {
// log.Error().Err(err).Msg("server shutdown")
//}
//time.Sleep(time.Second * 2)
if err := rpc.Shutdown(ctx); err != nil {
log.Error().Err(err).Msg("rpc Shutdown")
}
log.Info().Msg(srvName + " server exit")
return
case syscall.SIGHUP:
// TODO reload
default:
return
}
}
}

View File

@@ -0,0 +1,146 @@
package config
import (
"flag"
"github.com/BurntSushi/toml"
"gitlab.33.cn/chat/dtalk/pkg/net/grpc"
xgrpc "gitlab.33.cn/chat/dtalk/pkg/net/grpc"
"gitlab.33.cn/chat/dtalk/pkg/redis"
xtime "gitlab.33.cn/chat/dtalk/pkg/time"
"time"
)
var (
confPath string
Conf *Config
)
func init() {
flag.StringVar(&confPath, "conf", "group.toml", "default config path.")
}
// Init init config.
func Init() (err error) {
Conf = Default()
_, err = toml.DecodeFile(confPath, &Conf)
return
}
func Default() *Config {
return &Config{
HttpServer: &HttpServer{
Addr: "0.0.0.0:18011",
},
MySQL: &MySQL{
Host: "127.0.0.1",
Port: 3306,
User: "root",
Pwd: "123456",
Db: "dtalk",
},
Reg: &Reg{
Schema: "dtalk",
SrvName: "group",
RegAddrs: "127.0.0.1:2379",
},
LogicRPCClient: &RPCClient{
RegAddrs: "127.0.0.1:2379",
Schema: "im",
SrvName: "logic",
Dial: xtime.Duration(time.Second),
Timeout: xtime.Duration(time.Second),
},
IdGenRPCClient: &RPCClient{
RegAddrs: "127.0.0.1:2379",
Schema: "dtalk",
SrvName: "generator",
Dial: xtime.Duration(time.Second),
Timeout: xtime.Duration(time.Second),
},
AnswerRPCClient: &RPCClient{
RegAddrs: "127.0.0.1:2379",
Schema: "dtalk",
SrvName: "answer",
Dial: xtime.Duration(time.Second),
Timeout: xtime.Duration(time.Second),
},
GRPCServer: &xgrpc.ServerConfig{
Network: "tcp",
Addr: ":18012",
Timeout: xtime.Duration(time.Second),
KeepAliveMaxConnectionIdle: xtime.Duration(time.Second * 60),
KeepAliveMaxConnectionAge: xtime.Duration(time.Hour * 2),
KeepAliveMaxMaxConnectionAgeGrace: xtime.Duration(time.Second * 20),
KeepAliveTime: xtime.Duration(time.Second * 60),
KeepAliveTimeout: xtime.Duration(time.Second * 20),
},
GroupInfoConfig: &GroupDefault{
GroupMaximum: 200,
AdminNum: 10,
},
Redis: &redis.Config{
Network: "tcp",
Addr: "127.0.0.1:6379",
Auth: "",
Active: 60000,
Idle: 1024,
DialTimeout: xtime.Duration(200 * time.Millisecond),
ReadTimeout: xtime.Duration(500 * time.Millisecond),
WriteTimeout: xtime.Duration(500 * time.Millisecond),
IdleTimeout: xtime.Duration(120 * time.Second),
Expire: xtime.Duration(30 * time.Minute),
},
}
}
type Config struct {
Env string
AppId string
HttpServer *HttpServer
MySQL *MySQL
Reg *Reg
LogicRPCClient *RPCClient
IdGenRPCClient *RPCClient
//PusherRPCClient *RPCClient
AnswerRPCClient *RPCClient
//gRPC server
GRPCServer *grpc.ServerConfig
GroupInfoConfig *GroupDefault
Redis *redis.Config
}
type HttpServer struct {
Addr string
}
type MySQL struct {
Host string
Port int32
User string
Pwd string
Db string
}
// Reg is service register/discovery config
type Reg struct {
Schema string
SrvName string // call
RegAddrs string // etcd addrs, seperate by ','
}
// RPCClient is RPC client config.
type RPCClient struct {
RegAddrs string
Schema string
SrvName string // call
Dial xtime.Duration
Timeout xtime.Duration
}
type GroupDefault struct {
// 群人数上限 [200, 2000]
GroupMaximum int32
// 群管理员人数上限 [10, 10]
AdminNum int32
}

View File

@@ -0,0 +1,64 @@
Env="debug"
AppId= "dtalk"
[HttpServer]
Addr="0.0.0.0:18011"
[MySQL]
Host = "172.16.101.107"
Port = 3306
User= "root"
Pwd= "123456"
Db= "dtalk"
[Reg]
Schema = "dtalk"
SrvName = "group"
RegAddrs = "127.0.0.1:2379"
[LogicRPCClient]
RegAddrs = "172.16.101.107:2379"
Schema = "im"
SrvName = "logic"
Dial = "1s"
Timeout = "1s"
[IdGenRPCClient]
RegAddrs = "172.16.101.107:2379"
Schema = "dtalk"
SrvName = "generator"
Dial = "1s"
Timeout = "1s"
[AnswerRPCClient]
RegAddrs = "172.16.101.107:2379"
Schema = "dtalk"
SrvName = "answer"
Dial = "1s"
Timeout = "1s"
[GRPCServer]
Network= "tcp"
Addr= ":18012"
Timeout= "1s"
KeepAliveMaxConnectionIdle= "60s"
KeepAliveMaxConnectionAge= "2h"
KeepAliveMaxMaxConnectionAgeGrace= "20s"
KeepAliveTime= "60s"
KeepAliveTimeout= "20s"
[Group]
GroupMaximum = 2000
AdminNum = 10
[Redis]
network = "tcp"
addr = "127.0.0.1:6379"
auth = ""
active = 60000
idle = 1024
dialTimeout = "200ms"
readTimeout = "500ms"
writeTimeout = "500ms"
idleTimeout = "120s"
expire = "30m"

76
service/group/dao/dao.go Normal file
View File

@@ -0,0 +1,76 @@
package dao
import (
"context"
"fmt"
"os"
"time"
"github.com/rs/zerolog"
zlog "github.com/rs/zerolog/log"
"gitlab.33.cn/chat/dtalk/pkg/api/trace"
"gitlab.33.cn/chat/dtalk/pkg/mysql"
"gitlab.33.cn/chat/dtalk/pkg/redis"
"gitlab.33.cn/chat/dtalk/service/group/config"
"gitlab.33.cn/utils/go-kit/math"
)
var srvName = "group/dao"
type Dao struct {
log zerolog.Logger
conn *mysql.MysqlConn
// redis 连接
redis *redis.Pool
// redis 过期时间
redisExpire time.Duration
}
func New(c *config.Config) *Dao {
d := &Dao{
log: zlog.Logger.With().Str("service", srvName).Logger(),
conn: newDB(c.MySQL),
redis: redis.New(c.Redis),
redisExpire: time.Duration(c.Redis.Expire),
}
//log init
zerolog.SetGlobalLevel(zerolog.InfoLevel)
if config.Conf.Env == "debug" {
d.log = zlog.Output(zerolog.ConsoleWriter{Out: os.Stdout}).With().Str("service", srvName).Logger()
zerolog.SetGlobalLevel(zerolog.DebugLevel)
} else if config.Conf.Env == "benchmark" {
zerolog.SetGlobalLevel(zerolog.Disabled)
}
return d
}
func newDB(cfg *config.MySQL) *mysql.MysqlConn {
c, err := mysql.NewMysqlConn(cfg.Host, fmt.Sprintf("%v", cfg.Port),
cfg.User, cfg.Pwd, cfg.Db, "UTF8MB4")
if err != nil {
panic(err)
}
return c
}
func (d *Dao) NewTx() (*mysql.MysqlTx, error) {
return d.conn.NewTx()
}
func (d *Dao) GetLogWithTrace(ctx context.Context) zerolog.Logger {
logId := d.GetTrace(ctx)
return d.log.With().Str("trace", logId).Logger()
}
func (d *Dao) GetTrace(ctx context.Context) string {
return trace.NewTraceIdWithContext(ctx)
}
func (d *Dao) GetRandRedisExpire() time.Duration {
return (time.Duration(math.RandInt(0, 100))*time.Second + time.Duration(d.redisExpire)) / time.Second
}
func (d *Dao) getNowTime() int64 {
return time.Now().UnixNano() / 1e6
}

View File

@@ -0,0 +1,27 @@
package dao
import (
"os"
"testing"
"github.com/inconshreveable/log15"
"gitlab.33.cn/chat/dtalk/pkg/mysql"
"gitlab.33.cn/chat/dtalk/service/group/config"
)
var (
testLog log15.Logger
testConn *mysql.MysqlConn
)
func TestMain(m *testing.M) {
testConn = newDB(&config.MySQL{
Host: "127.0.0.1",
Port: 3306,
User: "root",
Pwd: "123456",
Db: "dtalk",
})
testLog = log15.New("model", "group/test")
os.Exit(m.Run())
}

417
service/group/dao/data.go Normal file
View File

@@ -0,0 +1,417 @@
package dao
import (
"context"
"github.com/pkg/errors"
"gitlab.33.cn/chat/dtalk/pkg/mysql"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/utils/go-kit/convert"
)
// 数据读写层,数据库和缓存全部在这层统一处理,包括 cache miss 处理。
// GetAllGroupInfo .
func (d *Dao) GetAllGroupInfo() ([]*biz.GroupInfo, error) {
groupPos, err := d.getAllGroupInfo()
if err != nil {
return nil, err
}
groups := make([]*biz.GroupInfo, 0, len(groupPos))
for i := range groupPos {
groups = append(groups, groupPos[i].ToBiz())
}
return groups, nil
}
// GetGroupInfoByGroupMarkId 查询群信息
func (d *Dao) GetGroupInfoByGroupMarkId(groupMarkId string) (*biz.GroupInfo, error) {
// redis get
groupInfo, err := d.getGroupInfoByGroupMarkId(groupMarkId)
if err != nil {
return nil, err
}
// redis put
return groupInfo.ToBiz(), nil
}
// GetGroupInfoByGroupId 查询群信息
func (d *Dao) GetGroupInfoByGroupId(ctx context.Context, groupId int64) (*biz.GroupInfo, error) {
log := d.GetLogWithTrace(ctx)
// 加缓存 get
group, err := d.GetGroupCache(groupId)
if err != nil {
//log.Warn().Err(err).Int64("groupId", groupId).Msg("GetGroupCache err")
} else {
return group, nil
}
groupInfo, err := d.getGroupInfoByGroupId(groupId)
if err != nil {
return nil, err
}
res := groupInfo.ToBiz()
muteNum, err := d.GetGroupMuteNum(groupId)
if err != nil {
return nil, err
}
res.MuteNum = muteNum
adminNum, err := d.getAdminNumByGroupId(groupId)
if err != nil {
return nil, err
}
res.AdminNum = adminNum
// 加缓存 set 设置固定值+随机的过期时间
expire := d.GetRandRedisExpire()
err = d.SaveGroup(res, expire)
if err != nil {
log.Warn().Err(err).Int64("groupId", groupId).Msg("SaveGroup err")
}
return res, nil
}
// GetGroupInfosByGroupIds 查询群信息s
func (d *Dao) GetGroupInfosByGroupIds(ctx context.Context, groupIds []int64) ([]*biz.GroupInfo, error) {
groupInfos, err := d.getGroupInfosByGroupIds(groupIds)
if err != nil {
return nil, err
}
ress := make([]*biz.GroupInfo, 0, len(groupInfos))
for _, groupInfo := range groupInfos {
ress = append(ress, groupInfo.ToBiz())
}
return ress, nil
}
// GetGroupIdsByMemberId 查询用户所有加入的群 ID
func (d *Dao) GetGroupIdsByMemberId(memberId string) ([]int64, error) {
groupIds, err := d.getGroupIdsByMemberId(memberId)
if err != nil {
return nil, errors.WithMessagef(err, "getGroupIdsByMemberId memberId=%s", memberId)
}
return groupIds, nil
}
// GetMembersByGroupId 查询群里的所有成员信息
func (d *Dao) GetMembersByGroupId(groupId int64) ([]*biz.GroupMember, error) {
res, err := d.getMembersByGroupId(groupId)
if err != nil {
return nil, err
}
groupMembers := make([]*biz.GroupMember, 0)
for _, groupMember := range res {
groupMembers = append(groupMembers, groupMember.ToBiz())
}
return groupMembers, nil
}
// GetGroupMembersByGroupIdWithLimit 查询群内前 n 个群成员信息
func (d *Dao) GetGroupMembersByGroupIdWithLimit(groupId, n, m int64) ([]*biz.GroupMember, error) {
members, err := d.getMembersByGroupIdWithLimit(groupId, n, m)
if err != nil {
return nil, err
}
groupMembers := make([]*biz.GroupMember, 0)
for _, groupMember := range members {
groupMembers = append(groupMembers, groupMember.ToBiz())
}
return groupMembers, nil
}
// UpdateGroupInfoMemberNum 更新群成员数量
func (d *Dao) UpdateGroupInfoMemberNum(ctx context.Context, groupId int64) (int32, error) {
log := d.GetLogWithTrace(ctx)
members, err := d.GetMembersByGroupId(groupId)
if err != nil {
return 0, errors.WithMessagef(err, "GetMembersByGroupId, groupId=%d", groupId)
}
newNum := convert.ToInt32(len(members))
nowTime := d.getNowTime()
groupInfo := &db.GroupInfo{
GroupId: groupId,
GroupMemberNum: newNum,
GroupUpdateTime: nowTime,
}
_, _, err = d.updateGroupInfoMemberNum(groupInfo)
if err != nil {
return 0, errors.WithMessagef(err, "UpdateGroupInfoMemberNum, groupId=%d", groupId)
}
// 删 group 缓存
err = d.DeleteGroupCache(groupId)
if err != nil {
log.Err(err).Int64("groupId", groupId).Msg("DeleteGroupCache err")
}
return newNum, nil
}
// UpdateGroupInfoName 更新群名称
func (d *Dao) UpdateGroupInfoName(ctx context.Context, groupId int64, name, publicName string) error {
log := d.GetLogWithTrace(ctx)
nowTime := d.getNowTime()
groupInfo := &db.GroupInfo{
GroupId: groupId,
GroupName: name,
GroupUpdateTime: nowTime,
GroupPubName: publicName,
}
if _, _, err := d.updateGroupInfoName(groupInfo); err != nil {
return errors.WithMessagef(err, "UpdateGroupInfoName, groupInfo=%+v", groupInfo)
}
// 删 group 缓存
err := d.DeleteGroupCache(groupId)
if err != nil {
log.Warn().Err(err).Int64("groupId", groupId).Msg("DeleteGroupCache err")
}
return nil
}
// UpdateGroupInfoAvatar 更新群头像
func (d *Dao) UpdateGroupInfoAvatar(ctx context.Context, groupId int64, avatar string) error {
log := d.GetLogWithTrace(ctx)
nowTime := d.getNowTime()
groupInfo := &db.GroupInfo{
GroupId: groupId,
GroupAvatar: avatar,
GroupUpdateTime: nowTime,
}
if _, _, err := d.updateGroupInfoAvatar(groupInfo); err != nil {
return errors.WithMessagef(err, "updateGroupInfoAvatar, groupInfo=%+v", groupInfo)
}
// 删 group 缓存
err := d.DeleteGroupCache(groupId)
if err != nil {
log.Warn().Err(err).Int64("groupId", groupId).Msg("DeleteGroupCache err")
}
return nil
}
// UpdateGroupInfoJoinType 更新加群设置
func (d *Dao) UpdateGroupInfoJoinType(ctx context.Context, groupId int64, joinType int32) error {
log := d.GetLogWithTrace(ctx)
nowTime := d.getNowTime()
groupInfo := &db.GroupInfo{
GroupId: groupId,
GroupJoinType: joinType,
GroupUpdateTime: nowTime,
}
if _, _, err := d.updateGroupInfoJoinType(groupInfo); err != nil {
return errors.WithMessagef(err, "updateGroupInfoJoinType, groupInfo=%+v", groupInfo)
}
// 删 group 缓存
err := d.DeleteGroupCache(groupId)
if err != nil {
log.Warn().Err(err).Int64("groupId", groupId).Msg("DeleteGroupCache err")
}
return nil
}
// UpdateGroupInfoFriendType 更新群内加好友设置
func (d *Dao) UpdateGroupInfoFriendType(ctx context.Context, groupId int64, friendType int32) error {
log := d.GetLogWithTrace(ctx)
nowTime := d.getNowTime()
groupInfo := &db.GroupInfo{
GroupId: groupId,
GroupFriendType: friendType,
GroupUpdateTime: nowTime,
}
if _, _, err := d.updateGroupInfoFriendType(groupInfo); err != nil {
return errors.WithMessagef(err, "UpdateGroupInfoFriendType, groupInfo=%+v", groupInfo)
}
// 删 group 缓存
err := d.DeleteGroupCache(groupId)
if err != nil {
log.Warn().Err(err).Int64("groupId", groupId).Msg("DeleteGroupCache err")
}
return nil
}
// UpdateGroupInfoMuteType 更新群禁言设置
func (d *Dao) UpdateGroupInfoMuteType(ctx context.Context, groupId int64, muteType int32) error {
log := d.GetLogWithTrace(ctx)
nowTime := d.getNowTime()
groupInfo := &db.GroupInfo{
GroupId: groupId,
GroupMuteType: muteType,
GroupUpdateTime: nowTime,
}
if _, _, err := d.updateGroupInfoMuteType(groupInfo); err != nil {
return errors.WithMessagef(err, "UpdateGroupInfoMuteType, groupInfo=%+v", groupInfo)
}
// 删 group 缓存
err := d.DeleteGroupCache(groupId)
if err != nil {
log.Warn().Err(err).Int64("groupId", groupId).Msg("DeleteGroupCache err")
}
return nil
}
//UpdateGroupMemberName 更新群成员昵称
func (d *Dao) UpdateGroupMemberName(groupId int64, memberId, memberName string) error {
nowTime := d.getNowTime()
groupMember := &db.GroupMember{
GroupId: groupId,
GroupMemberId: memberId,
GroupMemberName: memberName,
GroupMemberUpdateTime: nowTime,
}
if _, _, err := d.updateGroupMemberName(groupMember); err != nil {
return errors.WithMessagef(err, "UpdateGroupMemberName, groupMember=%+v", groupMember)
}
return nil
}
// UpdateGroupMemberType 更新群成员类型
func (d *Dao) UpdateGroupMemberType(ctx context.Context, groupId int64, mnemberId string, memberType int32) error {
log := d.GetLogWithTrace(ctx)
nowTime := d.getNowTime()
groupMember := &db.GroupMember{
GroupId: groupId,
GroupMemberId: mnemberId,
GroupMemberType: memberType,
GroupMemberUpdateTime: nowTime,
}
if _, _, err := d.updateGroupMemberType(groupMember); err != nil {
return errors.WithMessagef(err, "UpdateGroupMemberType, groupMember=%+v", groupMember)
}
err := d.DeleteGroupCache(groupId)
if err != nil {
log.Warn().Err(err).Int64("groupId", groupId).Msg("DeleteGroupCache err")
}
return nil
}
// GetAdminNumByGroupId 查询群内管理员数量
func (d *Dao) GetAdminNumByGroupId(groupId int64) (int32, error) {
num, err := d.getAdminNumByGroupId(groupId)
if err != nil {
return 0, errors.WithMessagef(err, "GetAdminNumByGroupId, groupId=%d", groupId)
}
return num, nil
}
// InsertGroupMembers 批量插入群成员
func (d *Dao) InsertGroupMembers(tx *mysql.MysqlTx, groupMembers []*db.GroupMember) error {
if len(groupMembers) == 0 {
return nil
}
_, _, err := d.insertGroupMembers(tx, groupMembers)
if err != nil {
return errors.WithMessagef(err, "InsertGroupMembers, groupMembers=%v", groupMembers)
}
_ = d.DeleteGroupCache(groupMembers[0].GroupId)
return nil
}
// GetGroupMemberMuteTime 查询群成员禁言时间
func (d *Dao) GetGroupMemberMuteTime(groupId int64, memberId string) (int64, error) {
muteTime, err := d.getGroupMemberMuteTime(groupId, memberId)
if err != nil {
return 0, errors.WithMessagef(err, "GetGroupMemberMuteTime groupId=%d, memberId=%s", groupId, memberId)
}
return muteTime, nil
}
// GetGroupMuteNum 查询群内禁言人数
func (d *Dao) GetGroupMuteNum(groupId int64) (int32, error) {
nowTime := d.getNowTime()
muteNum, err := d.getGroupMuteNum(groupId, nowTime)
if err != nil {
return 0, errors.WithMessagef(err, "GetGroupMuteNum groupId=%d, nowTime=%d", groupId, nowTime)
}
return muteNum, nil
}
// GetGroupMemberByGroupIdAndMemberId 查询一个群成员信息
func (d *Dao) GetGroupMemberByGroupIdAndMemberId(ctx context.Context, groupId int64, memberId string) (*biz.GroupMember, error) {
//log := d.GetLogWithTrace(ctx)
//加缓存 get
//groupMember, err := d.GetGroupMemberWithMuteTime(groupId, memberId)
//if err != nil {
// log.Warn().Err(err).Int64("groupId", groupId).Str("memberId", memberId).Msg("GetGroupMemberWithMuteTime")
//} else {
// return groupMember.ToBiz(), nil
//}
groupMember, err := d.getGroupMemberWithMuteTime(groupId, memberId)
if err != nil {
return nil, err
}
// 加缓存 set 设置固定值+随机的过期时间
//expire := d.GetRandRedisExpire()
//err = d.SaveGroupMemberWithMuteTime(groupMember, expire)
//if err != nil {
// log.Warn().Err(err).Int64("groupId", groupId).Str("memberId", memberId).Msg("SaveGroupMemberWithMuteTime")
//}
return groupMember.ToBiz(), nil
}
// GetGroupMembersMutedByGroupId 查询群内被禁言的群成员信息
func (d *Dao) GetGroupMembersMutedByGroupId(groupId int64) ([]*biz.GroupMember, error) {
nowTime := d.getNowTime()
muteList, err := d.getGroupMuteList(groupId, nowTime)
if err != nil {
return nil, err
}
groupMembers := make([]*biz.GroupMember, 0)
for _, groupMember := range muteList {
groupMembers = append(groupMembers, groupMember.ToBiz())
}
return groupMembers, nil
}
// GetGroupMemberWithMuteTimeByGroupIdAndMemberId 查询一个带禁言时间的群成员信息
// 没用 删掉
func (d *Dao) GetGroupMemberWithMuteTimeByGroupIdAndMemberId(groupId int64, memberId string) (*biz.GroupMember, error) {
member, err := d.getGroupMemberWithMuteTime(groupId, memberId)
if err != nil {
err = errors.WithMessagef(err, "GetGroupMemberWithMuteTimeByGroupIdAndMemberId GetGroupMemberWithMuteTime groupId=%d, memberId=%s", groupId, memberId)
return nil, err
}
return member.ToBiz(), nil
}
func (d *Dao) UpdateGroupMemberMuteTimes(ctx context.Context, tx *mysql.MysqlTx, groupMemberMutes []*db.GroupMemberMute) error {
if len(groupMemberMutes) == 0 {
return nil
}
log := d.GetLogWithTrace(ctx)
if _, _, err := d.updateGroupMemberMuteTimes(tx, groupMemberMutes); err != nil {
return errors.WithMessagef(err, "UpdateGroupMemberMuteTimes, groupMemberMutes=%+v", groupMemberMutes)
}
// 删 group 缓存
groupId := groupMemberMutes[0].GroupId
err := d.DeleteGroupCache(groupId)
if err != nil {
log.Warn().Err(err).Int64("groupId", groupId).Msg("DeleteGroupCache err")
}
return nil
}

470
service/group/dao/db.go Normal file
View File

@@ -0,0 +1,470 @@
package dao
import (
"gitlab.33.cn/chat/dtalk/pkg/mysql"
"gitlab.33.cn/chat/dtalk/service/group/model"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/utils/go-kit/convert"
"strings"
)
const (
// dtalk_group_info
_InsertGroupInfo = `INSERT INTO dtalk_group_info ( group_id, group_mark_id, group_name, group_avatar, group_member_num, group_maximum,
group_introduce, group_status, group_owner_id, group_create_time, group_update_time, group_join_type,
group_mute_type, group_friend_type, group_aes_key, group_pub_name, group_type )
VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )`
_UpdateGroupInfoName = `UPDATE dtalk_group_info SET group_name=?, group_pub_name=?, group_update_time=?
WHERE group_id=?`
_UpdateGroupInfoAvatar = `UPDATE dtalk_group_info SET group_avatar=?, group_update_time=?
WHERE group_id=?`
_UpdateGroupInfoGroupNum = `UPDATE dtalk_group_info SET group_member_num=?, group_update_time=?
WHERE group_id=?`
_UpdateGroupInfoMaximum = `UPDATE dtalk_group_info SET group_maximum=?, group_update_time=?
WHERE group_id=?`
_UpdateGroupInfoIntroduce = `UPDATE dtalk_group_info SET group_introduce=?, group_update_time=?
WHERE group_id=?`
_UpdateGroupInfoStatus = `UPDATE dtalk_group_info SET group_status=?, group_update_time=?
WHERE group_id=?`
_UpdateGroupInfoOwnerId = `UPDATE dtalk_group_info SET group_owner_id=?, group_update_time=?
WHERE group_id=?`
_UpdateGroupInfoJoinType = `UPDATE dtalk_group_info SET group_join_type=?, group_update_time=?
WHERE group_id=?`
_UpdateGroupInfoMuteType = `UPDATE dtalk_group_info SET group_mute_type=?, group_update_time=?
WHERE group_id=?`
_UpdateGroupInfoFriendType = `UPDATE dtalk_group_info SET group_friend_type=?, group_update_time=?
WHERE group_id=?`
_GetGroupInfoByGroupId = `SELECT * FROM dtalk_group_info WHERE group_id=?`
_GetGroupInfosByGroupIds = `SELECT * FROM dtalk_group_info WHERE group_id IN (?)`
_GetGroupInfoByGroupMarkId = `SELECT * FROM dtalk_group_info WHERE group_mark_id=?`
_GetAllGroupInfo = `SELECT * FROM dtalk_group_info`
_MaintainAESKeyAndPubName = `UPDATE dtalk_group_info SET group_aes_key=?, group_pub_name=? WHERE group_id=?`
_MaintainGroupType = `UPDATE dtalk_group_info SET group_type=?, group_join_type=? WHERE group_id=?`
// dtalk_group_member
_InsertGroupMember = `INSERT INTO dtalk_group_member ( group_id, group_member_id, group_member_name, group_member_type,
group_member_join_time, group_member_update_time) VALUES ( ?, ?, ?, ?, ?, ? )
ON DUPLICATE KEY UPDATE group_member_type=?, group_member_join_time=?,
group_member_update_time=?`
_InsertGroupMembersPrefix = `INSERT INTO dtalk_group_member ( group_id, group_member_id, group_member_name, group_member_type,
group_member_join_time, group_member_update_time) VALUES `
_InsertGroupMembersSuffix = `ON DUPLICATE KEY UPDATE group_member_name='', group_member_type=?, group_member_join_time=?,
group_member_update_time=?`
_UpdateGroupMemberName = `UPDATE dtalk_group_member SET group_member_name=?, group_member_update_time=?
WHERE group_id=? AND group_member_id=?`
_UpdateGroupMemberType = `UPDATE dtalk_group_member SET group_member_type=?, group_member_update_time=?
WHERE group_id=? AND group_member_id=?`
_GetGroupIdsByMemberId = `SELECT group_id FROM dtalk_group_member WHERE group_member_id=? AND group_member_type<?`
_GetMemberInfoByMemberIdAndGroupId = `SELECT * FROM dtalk_group_member WHERE group_id=? AND group_member_id=? AND group_member_type<?`
_GetMembersByGroupIdWithLimit = `
SELECT
mem.group_id as group_id,
mem.group_member_id as group_member_id,
mem.group_member_type as group_member_type,
mem.group_member_name as group_member_name,
mem.group_member_join_time as group_member_join_time,
mute.group_member_mute_time as group_member_mute_time
From dtalk_group_member AS mem LEFT JOIN dtalk_group_member_mute AS mute
ON mem.group_id=mute.group_id AND mem.group_member_id=mute.group_member_id
WHERE mem.group_id=? AND mem.group_member_type<? ORDER BY group_member_type desc, group_member_join_time ASC limit ?, ?
`
_GetMembersByGroupId = `
SELECT
mem.group_id as group_id,
mem.group_member_id as group_member_id,
mem.group_member_type as group_member_type,
mem.group_member_name as group_member_name,
mem.group_member_join_time as group_member_join_time,
mute.group_member_mute_time as group_member_mute_time
From dtalk_group_member AS mem LEFT JOIN dtalk_group_member_mute AS mute
ON mem.group_id=mute.group_id AND mem.group_member_id=mute.group_member_id
WHERE mem.group_id=? AND mem.group_member_type<? ORDER BY group_member_type desc, group_member_join_time ASC
`
_GetMemberTypeByMemberIdAndGroupId = `SELECT group_member_type FROM dtalk_group_member WHERE group_id=? AND group_member_id=?`
_GetAdminNumByGroupId = `SELECT count(*) FROM dtalk_group_member WHERE group_id=? AND group_member_type=?`
_GetMemberNumByGroupId = `SELECT count(*) FROM dtalk_group_member WHERE group_id=? AND group_member_type<?`
// dtalk_group_member_mute
_UpdateGroupMemberMuteTime = `REPLACE INTO dtalk_group_member_mute (group_id, group_member_id, group_member_mute_time, group_member_mute_update_time) VALUES`
_GetGroupMemberMuteTime = `SELECT group_member_mute_time FROM dtalk_group_member_mute WHERE group_id=? AND group_member_id=?`
_GetGroupMuteNum = `SELECT count(*) From dtalk_group_member AS mem LEFT JOIN dtalk_group_member_mute AS mute
ON mem.group_id=mute.group_id AND mem.group_member_id=mute.group_member_id
WHERE mem.group_id=? AND mem.group_member_type<? AND mute.group_member_mute_time>?`
_GetGroupMembersMuted = `SELECT
mem.group_id as group_id,
mem.group_member_id as group_member_id,
mem.group_member_type as group_member_type,
mem.group_member_name as group_member_name,
mute.group_member_mute_time as group_member_mute_time
From dtalk_group_member AS mem LEFT JOIN dtalk_group_member_mute AS mute
ON mem.group_id=mute.group_id AND mem.group_member_id=mute.group_member_id
WHERE mem.group_id=? AND mem.group_member_type<? AND mute.group_member_mute_time>?`
_GetGroupMemberWithMuteTime = `SELECT
mem.group_id as group_id,
mem.group_member_id as group_member_id,
mem.group_member_type as group_member_type,
mem.group_member_name as group_member_name,
mem.group_member_join_time as group_member_join_time,
mute.group_member_mute_time as group_member_mute_time
From dtalk_group_member AS mem LEFT JOIN dtalk_group_member_mute AS mute
ON mem.group_id=mute.group_id AND mem.group_member_id=mute.group_member_id
WHERE mem.group_id=? AND mem.group_member_id=? AND mem.group_member_type<?`
)
// dtalk_group_info
func (d *Dao) InsertGroupInfo(tx *mysql.MysqlTx, form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := tx.Exec(_InsertGroupInfo, form.GroupId, form.GroupMarkId, form.GroupName, form.GroupAvatar, form.GroupMemberNum, form.GroupMaximum,
form.GroupIntroduce, form.GroupStatus, form.GroupOwnerId, nowTime, nowTime,
form.GroupJoinType, form.GroupMuteType, form.GroupFriendType, form.GroupAESKey, form.GroupPubName, form.GroupType)
return num, lastId, err
}
func (d *Dao) updateGroupInfoName(form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupInfoName, form.GroupName, form.GroupPubName, nowTime, form.GroupId)
return num, lastId, err
}
func (d *Dao) updateGroupInfoAvatar(form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupInfoAvatar, form.GroupAvatar, nowTime, form.GroupId)
return num, lastId, err
}
func (d *Dao) updateGroupInfoMemberNum(form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupInfoGroupNum, form.GroupMemberNum, nowTime, form.GroupId)
return num, lastId, err
}
// UpdateGroupInfoMaximum .
// no usage
func (d *Dao) UpdateGroupInfoMaximum(form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupInfoMaximum, form.GroupMaximum, nowTime, form.GroupId)
return num, lastId, err
}
// UpdateGroupInfoIntroduce .
// no usage
func (d *Dao) UpdateGroupInfoIntroduce(form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupInfoIntroduce, form.GroupIntroduce, nowTime, form.GroupId)
return num, lastId, err
}
// UpdateGroupInfoStatus .
// no usage
func (d *Dao) UpdateGroupInfoStatus(form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupInfoStatus, form.GroupStatus, nowTime, form.GroupId)
return num, lastId, err
}
func (d *Dao) UpdateGroupInfoStatusWithTx(tx *mysql.MysqlTx, form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := tx.Exec(_UpdateGroupInfoStatus, form.GroupStatus, nowTime, form.GroupId)
_ = d.DeleteGroupCache(form.GroupId)
return num, lastId, err
}
func (d *Dao) UpdateGroupInfoOwnerIdWithTx(tx *mysql.MysqlTx, form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := tx.Exec(_UpdateGroupInfoOwnerId, form.GroupOwnerId, nowTime, form.GroupId)
_ = d.DeleteGroupCache(form.GroupId)
return num, lastId, err
}
func (d *Dao) updateGroupInfoJoinType(form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupInfoJoinType, form.GroupJoinType, nowTime, form.GroupId)
return num, lastId, err
}
func (d *Dao) updateGroupInfoMuteType(form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupInfoMuteType, form.GroupMuteType, nowTime, form.GroupId)
return num, lastId, err
}
func (d *Dao) updateGroupInfoFriendType(form *db.GroupInfo) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupInfoFriendType, form.GroupFriendType, nowTime, form.GroupId)
return num, lastId, err
}
func (d *Dao) getGroupInfoByGroupMarkId(groupMarkId string) (*db.GroupInfo, error) {
maps, err := d.conn.Query(_GetGroupInfoByGroupMarkId, groupMarkId)
if err != nil {
return nil, err
}
if len(maps) == 0 {
return nil, model.ErrRecordNotExist
}
res := maps[0]
return db.ConvertGroupInfo(res), nil
}
func (d *Dao) getGroupInfoByGroupId(groupId int64) (*db.GroupInfo, error) {
maps, err := d.conn.Query(_GetGroupInfoByGroupId, groupId)
if err != nil {
return nil, err
}
if len(maps) == 0 {
return nil, model.ErrRecordNotExist
}
res := maps[0]
return db.ConvertGroupInfo(res), nil
}
func (d *Dao) getGroupInfosByGroupIds(groupIds []int64) ([]*db.GroupInfo, error) {
if len(groupIds) == 0 {
return nil, nil
}
groupIdsSQL := ""
for _, groupId := range groupIds {
groupIdsSQL += convert.ToString(groupId) + ","
}
groupIdsSQL = strings.TrimSuffix(groupIdsSQL, ",")
maps, err := d.conn.Query(_GetGroupInfosByGroupIds, groupIdsSQL)
if err != nil {
return nil, err
}
return db.ConvertGroupInfos(maps), nil
}
func (d *Dao) getAllGroupInfo() ([]*db.GroupInfo, error) {
maps, err := d.conn.Query(_GetAllGroupInfo)
if err != nil {
return nil, err
}
if len(maps) == 0 {
return nil, model.ErrRecordNotExist
}
res := make([]*db.GroupInfo, len(maps))
for i := range maps {
res[i] = db.ConvertGroupInfo(maps[i])
}
return res, nil
}
func (d *Dao) MaintainAESKeyAndPubName(form *db.GroupInfo) (int64, int64, error) {
num, lastId, err := d.conn.Exec(_MaintainAESKeyAndPubName, form.GroupAESKey, form.GroupPubName, form.GroupId)
_ = d.DeleteGroupCache(form.GroupId)
return num, lastId, err
}
func (d *Dao) MaintainGroupType(form *db.GroupInfo) (int64, int64, error) {
num, lastId, err := d.conn.Exec(_MaintainGroupType, form.GroupType, biz.GroupJoinTypeAdmin, form.GroupId)
_ = d.DeleteGroupCache(form.GroupId)
return num, lastId, err
}
// dtalk_group_member
// InsertGroupMember .
// no usage
func (d *Dao) InsertGroupMember(tx *mysql.MysqlTx, form *db.GroupMember) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := tx.Exec(_InsertGroupMember, form.GroupId, form.GroupMemberId, form.GroupMemberName,
form.GroupMemberType, nowTime, nowTime, form.GroupMemberType,
nowTime, nowTime)
return num, lastId, err
}
func (d *Dao) insertGroupMembers(tx *mysql.MysqlTx, groupMembers []*db.GroupMember) (int64, int64, error) {
nowTime := d.getNowTime()
var vals []interface{}
valSql := ""
for i, groupMember := range groupMembers {
if i == 0 {
valSql += "(?,?,?,?,?,?)"
} else {
valSql += ",(?,?,?,?,?,?)"
}
vals = append(vals, groupMember.GroupId, groupMember.GroupMemberId, groupMember.GroupMemberName, groupMember.GroupMemberType,
nowTime, nowTime)
}
SQL := _InsertGroupMembersPrefix + valSql + _InsertGroupMembersSuffix
vals = append(vals, biz.GroupMemberTypeNormal, nowTime, nowTime)
num, lastId, err := tx.Exec(SQL, vals...)
return num, lastId, err
}
func (d *Dao) updateGroupMemberName(form *db.GroupMember) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupMemberName, form.GroupMemberName, nowTime, form.GroupId, form.GroupMemberId)
return num, lastId, err
}
func (d *Dao) updateGroupMemberType(form *db.GroupMember) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := d.conn.Exec(_UpdateGroupMemberType, form.GroupMemberType, nowTime, form.GroupId, form.GroupMemberId)
return num, lastId, err
}
func (d *Dao) UpdateGroupMemberTypeWithTx(tx *mysql.MysqlTx, form *db.GroupMember) (int64, int64, error) {
nowTime := d.getNowTime()
num, lastId, err := tx.Exec(_UpdateGroupMemberType, form.GroupMemberType, nowTime, form.GroupId, form.GroupMemberId)
_ = d.DeleteGroupCache(form.GroupId)
return num, lastId, err
}
func (d *Dao) getGroupIdsByMemberId(memberId string) ([]int64, error) {
maps, err := d.conn.Query(_GetGroupIdsByMemberId, memberId, biz.GroupMemberTypeOther)
if err != nil {
return nil, err
}
ret := make([]int64, len(maps))
for i, m := range maps {
ret[i] = convert.ToInt64(m["group_id"])
}
return ret, err
}
func (d *Dao) getMemberInfoByMemberIdAndGroupId(groupMemberId string, groupId int64) (*db.GroupMember, error) {
maps, err := d.conn.Query(_GetMemberInfoByMemberIdAndGroupId, groupId, groupMemberId, biz.GroupMemberTypeOther)
if err != nil {
return nil, err
}
if len(maps) == 0 {
return nil, model.ErrRecordNotExist
}
res := maps[0]
return db.ConvertGroupMember(res), nil
}
func (d *Dao) getMembersByGroupId(groupId int64) ([]*db.GroupMemberWithMute, error) {
maps, err := d.conn.Query(_GetMembersByGroupId, groupId, biz.GroupMemberTypeOther)
if err != nil {
return nil, err
}
if len(maps) == 0 {
return nil, nil
}
res := make([]*db.GroupMemberWithMute, len(maps))
for i := range maps {
res[i] = db.ConvertGroupMemberWithMute(maps[i])
}
return res, nil
}
func (d *Dao) getMembersByGroupIdWithLimit(groupId, n, m int64) ([]*db.GroupMemberWithMute, error) {
maps, err := d.conn.Query(_GetMembersByGroupIdWithLimit, groupId, biz.GroupMemberTypeOther, n, m)
if err != nil {
return nil, err
}
if len(maps) == 0 {
return nil, nil
}
res := make([]*db.GroupMemberWithMute, len(maps))
for i := range maps {
res[i] = db.ConvertGroupMemberWithMute(maps[i])
}
return res, nil
}
func (d *Dao) GetMemberTypeMemberIdAndGroupId(groupMemberId string, groupId int64) (int32, error) {
maps, err := d.conn.Query(_GetMemberTypeByMemberIdAndGroupId, groupId, groupMemberId)
if err != nil {
return -1, err
}
if len(maps) == 0 {
return biz.GroupMemberTypeOther, nil
}
return convert.ToInt32(maps[0]["group_member_type"]), nil
}
func (d *Dao) getAdminNumByGroupId(groupId int64) (int32, error) {
res, err := d.conn.Query(_GetAdminNumByGroupId, groupId, biz.GroupMemberTypeAdmin)
if err != nil {
return 0, err
}
return convert.ToInt32(res[0]["count(*)"]), nil
}
func (d *Dao) getMemberNumByGroupId(groupId int64) (int32, error) {
res, err := d.conn.Query(_GetMemberNumByGroupId, groupId, biz.GroupMemberTypeOther)
if err != nil {
return 0, err
}
return convert.ToInt32(res[0]["count(*)"]), nil
}
// dtalk_group_member_mute
func (d *Dao) updateGroupMemberMuteTimes(tx *mysql.MysqlTx, groupMemberMutes []*db.GroupMemberMute) (int64, int64, error) {
nowTime := d.getNowTime()
var vals []interface{}
valSql := ""
for i, groupMemberMute := range groupMemberMutes {
if i == 0 {
valSql += "(?,?,?,?)"
} else {
valSql += ",(?,?,?,?)"
}
vals = append(vals, groupMemberMute.GroupId, groupMemberMute.GroupMemberId, groupMemberMute.GroupMemberMuteTime, nowTime)
}
SQL := _UpdateGroupMemberMuteTime + valSql
num, lastId, err := tx.Exec(SQL, vals...)
return num, lastId, err
}
func (d *Dao) getGroupMemberMuteTime(groupId int64, memberId string) (int64, error) {
maps, err := d.conn.Query(_GetGroupMemberMuteTime, groupId, memberId)
if err != nil {
return 0, err
}
if len(maps) == 0 {
return 0, nil
}
return convert.ToInt64(maps[0]["group_member_mute_time"]), nil
}
func (d *Dao) getGroupMuteNum(groupId int64, nowTime int64) (int32, error) {
res, err := d.conn.Query(_GetGroupMuteNum, groupId, biz.GroupMemberTypeOther, nowTime)
if err != nil {
return 0, err
}
return convert.ToInt32(res[0]["count(*)"]), nil
}
func (d *Dao) getGroupMuteList(groupId int64, nowTime int64) ([]*db.GroupMemberWithMute, error) {
maps, err := d.conn.Query(_GetGroupMembersMuted, groupId, biz.GroupMemberTypeOther, nowTime)
if err != nil {
return nil, err
}
if len(maps) == 0 {
return nil, nil
}
res := make([]*db.GroupMemberWithMute, len(maps))
for i := range maps {
res[i] = db.ConvertGroupMemberWithMute(maps[i])
}
return res, nil
}
func (d *Dao) getGroupMemberWithMuteTime(groupId int64, memberId string) (*db.GroupMemberWithMute, error) {
maps, err := d.conn.Query(_GetGroupMemberWithMuteTime, groupId, memberId, biz.GroupMemberTypeOther)
if err != nil {
return nil, err
}
if len(maps) == 0 {
return nil, model.ErrRecordNotExist
}
res := db.ConvertGroupMemberWithMute(maps[0])
return res, nil
}

View File

@@ -0,0 +1,84 @@
package dao
import (
"gitlab.33.cn/chat/dtalk/pkg/mysql"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
)
const (
_InsertGroupApplysPrefix = `INSERT INTO dtalk_group_apply ( id, group_id, inviter_id, member_id, apply_note,
operator_id, apply_status, reject_reason, create_time, update_time) VALUES `
_InsertGroupApplysSuffix = ``
_GetGroupApplyById = `SELECT * FROM dtalk_group_apply WHERE id=?`
_GetGroupApplys = `SELECT * FROM dtalk_group_apply WHERE group_id=? ORDER BY id desc LIMIT ?,?`
_UpdateGroupApply = `UPDATE dtalk_group_apply SET operator_id=?, apply_status=?, reject_reason=?, update_time=? WHERE id=?`
)
// dtalk_group_apply
// InsertGroupApplys 插入加群审批
func (d *Dao) InsertGroupApplys(tx *mysql.MysqlTx, groupApplys []*db.GroupApply) error {
var vals []interface{}
valSql := ""
for i, groupApply := range groupApplys {
if i == 0 {
valSql += "(?,?,?,?,?,?,?,?,?,?)"
} else {
valSql += ",(?,?,?,?,?,?,?,?,?,?)"
}
vals = append(vals,
groupApply.Id,
groupApply.GroupId,
groupApply.InviterId,
groupApply.MemberId,
groupApply.ApplyNote,
groupApply.OperatorId,
groupApply.ApplyStatus,
groupApply.RejectReason,
groupApply.CreateTime,
groupApply.UpdateTime,
)
}
SQL := _InsertGroupApplysPrefix + valSql + _InsertGroupApplysSuffix
_, _, err := tx.Exec(SQL, vals...)
return err
}
// GetGroupApplyById 通过 ID 获得群审批详情
func (d *Dao) GetGroupApplyById(id int64) (*db.GroupApply, error) {
maps, err := d.conn.Query(_GetGroupApplyById, id)
if err != nil {
return nil, err
}
if len(maps) == 0 {
return nil, nil
}
res := maps[0]
return db.ConvertGroupApply(res), nil
}
func (d *Dao) GetGroupApplys(groupId int64, limit, offset int32) ([]*db.GroupApply, error) {
maps, err := d.conn.Query(_GetGroupApplys, groupId, offset, limit)
if err != nil {
return nil, err
}
res := make([]*db.GroupApply, 0)
for _, m := range maps {
t := db.ConvertGroupApply(m)
res = append(res, t)
}
return res, nil
}
func (d *Dao) UpdateGroupApply(operatorId string, applyStatus int32, rejectReason string, id int64) error {
nowTime := d.getNowTime()
_, _, err := d.conn.Exec(_UpdateGroupApply, operatorId, applyStatus, rejectReason, nowTime, id)
return err
}

View File

@@ -0,0 +1,80 @@
package dao
import (
"fmt"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"time"
)
const (
_prefixGroup = "x_group:%d"
_prefixGroupMember = "x_group:%d;member:%s"
)
func keyGroup(groupId int64) string {
return fmt.Sprintf(_prefixGroup, groupId)
}
// GetGroupCache get group from groupId
func (d *Dao) GetGroupCache(groupId int64) (*biz.GroupInfo, error) {
key := keyGroup(groupId)
if ok, err := d.redis.Exists(key); err != nil {
return nil, err
} else if !ok {
return nil, db.ErrGroupNotExist
}
res := &biz.GroupInfo{}
if err := d.redis.Read(key, res); err != nil {
return nil, err
}
return res, nil
}
func (d *Dao) SaveGroup(group *biz.GroupInfo, duration time.Duration) error {
key := keyGroup(group.GroupId)
if err := d.redis.Write(key, group, int(duration)); err != nil {
return err
}
return nil
}
func (d *Dao) DeleteGroupCache(groupId int64) error {
key := keyGroup(groupId)
_, err := d.redis.Del(key)
if err != nil {
return err
}
return nil
}
//func keyGroupMember(groupId int64, memberId string) string {
// return fmt.Sprintf(_prefixGroupMember, groupId, memberId)
//}
//
//func (d *Dao) GetGroupMemberWithMuteTime(groupId int64, memberId string) (*db.GroupMemberWithMute, error) {
// key := keyGroupMember(groupId, memberId)
// if ok, err := d.redis.Exists(key); err != nil {
// return nil, err
// } else if !ok {
// return nil, db.ErrGroupMemberNotExist
// }
//
// res := &db.GroupMemberWithMute{}
// if err := d.redis.Read(key, res); err != nil {
// return nil, err
// }
//
// return res, nil
//}
//
//func (d *Dao) SaveGroupMemberWithMuteTime(member *db.GroupMemberWithMute, duration time.Duration) error {
// key := keyGroup(member.GroupId)
// if err := d.redis.Write(key, member, int(duration)); err != nil {
// return err
// }
// return nil
//}

2513
service/group/docs/docs.go Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
package logic
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type ChangeOwnerLogic struct {
ctx context.Context
svc *service.Service
}
func NewChangeOwnerLogic(ctx context.Context, svc *service.Service) *ChangeOwnerLogic {
return &ChangeOwnerLogic{
ctx: ctx,
svc: svc,
}
}
// ChangeOwner 退出群
func (l *ChangeOwnerLogic) ChangeOwner(req *pb.ChangeOwnerReq) (*pb.ChangeOwnerResp, error) {
groupId := req.GroupId
personId := req.PersonId
memberId := req.MemberId
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
member, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, memberId, groupId)
if err != nil {
return nil, err
}
// 只有群主可以转让群
if err = person.IsOwner(); err != nil {
return nil, err
}
if personId == memberId {
return nil, xerror.NewError(xerror.GroupChangeOwnerSelf)
}
err = l.svc.ChangeOwner(l.ctx, group, person, member)
if err != nil {
return nil, err
}
return &pb.ChangeOwnerResp{}, nil
}

View File

@@ -0,0 +1,65 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type CreateGroupLogic struct {
ctx context.Context
svc *service.Service
}
func NewCreateGroupLogic(ctx context.Context, svc *service.Service) *CreateGroupLogic {
return &CreateGroupLogic{
ctx: ctx,
svc: svc,
}
}
// CreateGroup 创建群聊
func (l *CreateGroupLogic) CreateGroup(req *pb.CreateGroupReq) (*pb.CreateGroupResp, error) {
var err error
req.Owner.Id, err = FilteredMemberId(req.Owner.Id)
if err != nil {
return nil, err
}
group := &biz.GroupInfo{
GroupName: req.Name,
GroupType: int32(req.GroupType),
}
owner := &biz.GroupMember{
GroupMemberId: req.Owner.Id,
GroupMemberName: req.Owner.Name,
}
members := make([]*biz.GroupMember, 0, len(req.Members))
for _, member := range req.Members {
if member.Id == owner.GroupMemberId {
continue
}
member.Id, err = FilteredMemberId(member.Id)
if err != nil {
return nil, err
}
members = append(members, &biz.GroupMember{
GroupMemberId: member.Id,
GroupMemberName: member.Name,
})
}
groupId, err := l.svc.CreateGroup(l.ctx, group, owner, members)
if err != nil {
return nil, err
}
return &pb.CreateGroupResp{
GroupId: groupId,
}, nil
}

View File

@@ -0,0 +1,47 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type ForceAddMemberLogic struct {
ctx context.Context
svc *service.Service
}
func NewForceAddMemberLogic(ctx context.Context, svc *service.Service) *ForceAddMemberLogic {
return &ForceAddMemberLogic{
ctx: ctx,
svc: svc,
}
}
// ForceAddMember 多个人加入一个群
// 无视操作者是否在群里, 是否有管理权限, 群人数是否已满
// 强行拉 member 进群
func (l *ForceAddMemberLogic) ForceAddMember(req *pb.ForceAddMemberReq) (*pb.ForceAddMemberResp, error) {
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, req.GroupId)
if err != nil {
return nil, err
}
members := make([]*biz.GroupMember, 0)
_, err = FilteredMemberId(req.MemberId)
members = append(members, &biz.GroupMember{
GroupId: group.GroupId,
GroupMemberId: req.MemberId,
GroupMemberName: "",
GroupMemberType: biz.GroupTypeNormal,
})
err = l.svc.AddMembers(l.ctx, group, members)
if err != nil {
return nil, err
}
return &pb.ForceAddMemberResp{}, nil
}

View File

@@ -0,0 +1,52 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type ForceAddMembersLogic struct {
ctx context.Context
svc *service.Service
}
func NewForceAddMembersLogic(ctx context.Context, svc *service.Service) *ForceAddMembersLogic {
return &ForceAddMembersLogic{
ctx: ctx,
svc: svc,
}
}
// ForceAddMembers 多个人加入一个群
// 无视操作者是否在群里, 是否有管理权限, 群人数是否已满
// 强行拉 member 进群
func (l *ForceAddMembersLogic) ForceAddMembers(req *pb.ForceAddMembersReq) (*pb.ForceAddMembersResp, error) {
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, req.GroupId)
if err != nil {
return nil, err
}
members := make([]*biz.GroupMember, 0, len(req.Members))
for _, member := range req.Members {
_, err := FilteredMemberId(member.Id)
if err != nil {
continue
}
members = append(members, &biz.GroupMember{
GroupId: group.GroupId,
GroupMemberId: member.Id,
GroupMemberName: member.Name,
GroupMemberType: biz.GroupTypeNormal,
})
}
err = l.svc.AddMembers(l.ctx, group, members)
if err != nil {
return nil, err
}
return &pb.ForceAddMembersResp{}, nil
}

View File

@@ -0,0 +1,54 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type ForceChangeOwnerLogic struct {
ctx context.Context
svc *service.Service
}
func NewForceChangeOwnerLogic(ctx context.Context, svc *service.Service) *ForceChangeOwnerLogic {
return &ForceChangeOwnerLogic{
ctx: ctx,
svc: svc,
}
}
// ForceChangeOwner .
func (l *ForceChangeOwnerLogic) ForceChangeOwner(req *pb.ForceChangeOwnerReq) (*pb.ForceChangeOwnerResp, error) {
_, err := FilteredMemberId(req.Member.Id)
if err != nil {
return nil, err
}
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, req.GroupId)
if err != nil {
return nil, err
}
// 判断这个人是否在群里
member, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, req.Member.Id, group.GroupId)
if err != nil {
return nil, err
}
owner, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, group.GroupOwnerId, group.GroupId)
if err != nil {
return nil, err
}
if member.GroupMemberId == owner.GroupMemberId {
return &pb.ForceChangeOwnerResp{}, nil
}
err = l.svc.ChangeOwner(l.ctx, group, owner, member)
if err != nil {
return nil, err
}
return &pb.ForceChangeOwnerResp{}, nil
}

View File

@@ -0,0 +1,77 @@
package logic
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type ForceDeleteMemberLogic struct {
ctx context.Context
svc *service.Service
}
func NewForceDeleteMemberLogic(ctx context.Context, svc *service.Service) *ForceDeleteMemberLogic {
return &ForceDeleteMemberLogic{
ctx: ctx,
svc: svc,
}
}
// ForceDeleteMember 一个人退出一个群
func (l *ForceDeleteMemberLogic) ForceDeleteMember(req *pb.ForceDeleteMemberReq) (*pb.ForceDeleteMemberResp, error) {
groupId := req.GroupId
memberId, err := FilteredMemberId(req.MemberId)
if err != nil {
return nil, err
}
// 判断群是否存在
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
// 判断这个人是否在群里
deleteMember, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, memberId, groupId)
if err != nil {
return nil, err
}
members, err := l.svc.GetGroupMembersByGroupIdWithLimit(group.GroupId, 0, 2)
if err != nil {
return nil, err
}
// 如果退群的人是群主
if group.GroupOwnerId == deleteMember.GroupMemberId {
// 如果群内有群主之外的人
if len(members) > 1 {
// 转让群主, 再到下面一起退群
// todo
err = l.svc.ChangeOwner(l.ctx, group, deleteMember, members[1])
if err != nil {
return nil, err
}
} else {
// 解散群
err = l.svc.GroupDisband(l.ctx, groupId, memberId)
if err != nil {
return nil, err
}
return &pb.ForceDeleteMemberResp{}, nil
}
}
// 退群
err = l.svc.RemoveGroupMembers(l.ctx, group, []*biz.GroupMember{deleteMember})
if err != nil {
return nil, err
}
return &pb.ForceDeleteMemberResp{}, nil
}

View File

@@ -0,0 +1,101 @@
package logic
import (
"context"
"github.com/rs/zerolog"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type ForceDeleteMembersLogic struct {
ctx context.Context
svc *service.Service
log zerolog.Logger
}
func NewForceDeleteMembersLogic(ctx context.Context, svc *service.Service) *ForceDeleteMembersLogic {
return &ForceDeleteMembersLogic{
ctx: ctx,
svc: svc,
log: svc.GetLog(),
}
}
// ForceDeleteMembers 多个人退出同一个群
func (l *ForceDeleteMembersLogic) ForceDeleteMembers(req *pb.ForceDeleteMembersReq) (*pb.ForceDeleteMembersResp, error) {
groupId := req.GroupId
// 判断群是否存在
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
needDeleteMembers := l.svc.GetFilteredGroupMembers(l.ctx, group, FilteredMemberIds(req.MemberIds))
if len(needDeleteMembers) == 0 {
return &pb.ForceDeleteMembersResp{}, nil
}
members, err := l.svc.GetGroupMembersByGroupIdWithLimit(group.GroupId, 0, int64(len(needDeleteMembers))+1)
if err != nil {
return nil, err
}
if len(needDeleteMembers) == len(members) {
// 解散群
err = l.svc.GroupDisband(l.ctx, groupId, l.svc.GetOpe(l.ctx))
if err != nil {
return nil, err
}
return &pb.ForceDeleteMembersResp{}, nil
}
owner, ok := hasOwner(needDeleteMembers)
if ok {
CandidateOwner := getCandidateOwner(members, needDeleteMembers)
err = l.svc.ChangeOwner(l.ctx, group, owner, CandidateOwner)
if err != nil {
return nil, err
}
}
// 退群
err = l.svc.RemoveGroupMembers(l.ctx, group, needDeleteMembers)
if err != nil {
return nil, err
}
return &pb.ForceDeleteMembersResp{}, nil
}
func hasOwner(members []*biz.GroupMember) (*biz.GroupMember, bool) {
for _, member := range members {
if err := member.IsOwner(); err == nil {
return member, true
}
}
return nil, false
}
func getCandidateOwner(members []*biz.GroupMember, deleteMembers []*biz.GroupMember) *biz.GroupMember {
for i := 0; i < len(members); i++ {
isDelete := false
for j := 0; j < len(deleteMembers); j++ {
if members[i].GroupMemberId == deleteMembers[j].GroupMemberId {
isDelete = true
break
}
}
if !isDelete {
return members[i]
}
}
return &biz.GroupMember{}
}

View File

@@ -0,0 +1,45 @@
package logic
import (
"context"
"github.com/rs/zerolog"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type ForceExitGroupsLogic struct {
ctx context.Context
svc *service.Service
log zerolog.Logger
}
func NewForceExitGroupsLogic(ctx context.Context, svc *service.Service) *ForceExitGroupsLogic {
return &ForceExitGroupsLogic{
ctx: ctx,
svc: svc,
log: svc.GetLog(),
}
}
// ForceExitGroups .
// todo: 没有好的想法
// 相当于多次 DeleteMember
func (l *ForceExitGroupsLogic) ForceExitGroups(req *pb.ForceExitGroupsReq) (*pb.ForceExitGroupsResp, error) {
_, err := FilteredMemberId(req.Member.Id)
if err != nil {
return nil, err
}
dml := NewForceDeleteMemberLogic(l.ctx, l.svc)
for _, groupId := range req.GroupIds {
_, err := dml.ForceDeleteMember(&pb.ForceDeleteMemberReq{
MemberId: req.Member.Id,
GroupId: groupId,
})
if err != nil {
l.log.Error().Err(err).Msg("ForceExitGroups")
}
}
return &pb.ForceExitGroupsResp{}, nil
}

View File

@@ -0,0 +1,53 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type ForceJoinGroupsLogic struct {
ctx context.Context
svc *service.Service
}
func NewForceJoinGroupsLogic(ctx context.Context, svc *service.Service) *ForceJoinGroupsLogic {
return &ForceJoinGroupsLogic{
ctx: ctx,
svc: svc,
}
}
// ForceJoinGroups 一个人加入多个群
// 相当于多次 AddMember
func (l *ForceJoinGroupsLogic) ForceJoinGroups(req *pb.ForceJoinGroupsReq) (*pb.ForceJoinGroupsResp, error) {
_, err := FilteredMemberId(req.Member.Id)
if err != nil {
return nil, err
}
groups := make([]*biz.GroupInfo, 0, len(req.GroupIds))
for _, groupId := range req.GroupIds {
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
continue
}
groups = append(groups, group)
}
members := make([]*biz.GroupMember, 0, len(groups))
for _, group := range groups {
members = append(members, &biz.GroupMember{
GroupId: group.GroupId,
GroupMemberId: req.Member.Id,
GroupMemberName: req.Member.Name,
GroupMemberType: biz.GroupMemberTypeNormal,
})
}
l.svc.JoinGroups(l.ctx, members)
return &pb.ForceJoinGroupsResp{}, nil
}

View File

@@ -0,0 +1,52 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type GetGroupListLogic struct {
ctx context.Context
svc *service.Service
}
func NewGetGroupListLogic(ctx context.Context, svc *service.Service) *GetGroupListLogic {
return &GetGroupListLogic{
ctx: ctx,
svc: svc,
}
}
// GetGroupList 查询加入的群列表
func (l *GetGroupListLogic) GetGroupList(req *pb.GetGroupListReq) (*pb.GetGroupListResp, error) {
groupIds, err := l.svc.GetGroupIdsByMemberId(req.PersonId)
if err != nil {
return nil, err
}
groupInfos := make([]*pb.GroupBizInfo, 0, len(groupIds))
for _, groupId := range groupIds {
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
owner, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, group.GroupOwnerId, group.GroupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, req.PersonId, group.GroupId)
if err != nil {
return nil, err
}
groupInfo := NewRPCGroupInfo(group)
groupInfo.Owner = NewRPCGroupMemberInfo(owner)
groupInfo.Person = NewRPCGroupMemberInfo(person)
groupInfos = append(groupInfos, groupInfo)
}
return &pb.GetGroupListResp{
Groups: groupInfos,
}, nil
}

View File

@@ -0,0 +1,45 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type GetGroupMemberInfoLogic struct {
ctx context.Context
svc *service.Service
}
func NewGetGroupMemberInfoLogic(ctx context.Context, svc *service.Service) *GetGroupMemberInfoLogic {
return &GetGroupMemberInfoLogic{
ctx: ctx,
svc: svc,
}
}
// GetGroupMemberInfo 查询一个人的信息
func (l *GetGroupMemberInfoLogic) GetGroupMemberInfo(req *pb.GetGroupMemberInfoReq) (*pb.GetGroupMemberInfoResp, error) {
groupId := req.GroupId
memberId := req.MemberId
personId := req.PersonId
_, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
_, err = l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
member, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, memberId, groupId)
if err != nil {
return nil, err
}
return &pb.GetGroupMemberInfoResp{
Member: NewRPCGroupMemberInfo(member),
}, nil
}

View File

@@ -0,0 +1,44 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type GetGroupMemberListLogic struct {
ctx context.Context
svc *service.Service
}
func NewGetGroupMemberListLogic(ctx context.Context, svc *service.Service) *GetGroupMemberListLogic {
return &GetGroupMemberListLogic{
ctx: ctx,
svc: svc,
}
}
// GetGroupMemberList 查询群成员列表
func (l *GetGroupMemberListLogic) GetGroupMemberList(req *pb.GetGroupMemberListReq) (*pb.GetGroupMemberListResp, error) {
groupId := req.GroupId
personId := req.PersonId
_, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
_, err = l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
groupMembers, err := l.svc.GetMembersByGroupId(groupId)
if err != nil {
return nil, err
}
return &pb.GetGroupMemberListResp{
Members: NewRPCGroupMemberInfos(groupMembers),
}, nil
}

View File

@@ -0,0 +1,47 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type GetMuteListLogic struct {
ctx context.Context
svc *service.Service
}
func NewGetMuteListLogic(ctx context.Context, svc *service.Service) *GetMuteListLogic {
return &GetMuteListLogic{
ctx: ctx,
svc: svc,
}
}
// GetMuteList 查询群禁言列表
func (l *GetMuteListLogic) GetMuteList(req *pb.GetMuteListReq) (*pb.GetMuteListResp, error) {
groupId := req.GroupId
personId := req.PersonId
_, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
muteList, err := l.svc.GetGroupMembersMutedByGroupId(groupId)
if err != nil {
return nil, err
}
return &pb.GetMuteListResp{
Members: NewRPCGroupMemberInfos(muteList),
}, nil
}

View File

@@ -0,0 +1,51 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type GetPriGroupInfoLogic struct {
ctx context.Context
svc *service.Service
}
func NewGetPriGroupInfoLogic(ctx context.Context, svc *service.Service) *GetPriGroupInfoLogic {
return &GetPriGroupInfoLogic{
ctx: ctx,
svc: svc,
}
}
// GetPriGroupInfo 查询群全部信息
func (l *GetPriGroupInfoLogic) GetPriGroupInfo(req *pb.GetPriGroupInfoReq) (*pb.GetPriGroupInfoResp, error) {
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, req.GroupId)
if err != nil {
return nil, err
}
owner, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, group.GroupOwnerId, group.GroupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, req.PersonId, req.GroupId)
if err != nil {
return nil, err
}
members, err := l.svc.GetGroupMembersByGroupIdWithLimit(group.GroupId, 0, int64(req.DisplayNum))
if err != nil {
return nil, err
}
groupInfo := NewRPCGroupInfo(group)
groupInfo.Owner = NewRPCGroupMemberInfo(owner)
groupInfo.Person = NewRPCGroupMemberInfo(person)
groupInfo.Members = NewRPCGroupMemberInfos(members)
return &pb.GetPriGroupInfoResp{
Group: groupInfo,
}, nil
}

View File

@@ -0,0 +1,53 @@
package logic
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type GetPubGroupInfoLogic struct {
ctx context.Context
svc *service.Service
}
func NewGetPubGroupInfoLogic(ctx context.Context, svc *service.Service) *GetPubGroupInfoLogic {
return &GetPubGroupInfoLogic{
ctx: ctx,
svc: svc,
}
}
// GetPubGroupInfo 查询群公开信息
func (l *GetPubGroupInfoLogic) GetPubGroupInfo(req *pb.GetPubGroupInfoReq) (*pb.GetPubGroupInfoResp, error) {
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, req.GroupId)
if err != nil {
return nil, err
}
owner, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, group.GroupOwnerId, group.GroupId)
if err != nil {
return nil, err
}
groupInfo := NewRPCGroupInfo(group)
groupInfo.Owner = NewRPCGroupMemberInfo(owner)
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, req.PersonId, req.GroupId)
if err != nil {
if xerror.NewError(xerror.GroupPersonNotExist).Error() != err.Error() {
return nil, err
}
}
if person == nil {
groupInfo.AESKey = ""
} else {
groupInfo.Person = NewRPCGroupMemberInfo(person)
}
return &pb.GetPubGroupInfoResp{
Group: groupInfo,
}, nil
}

View File

@@ -0,0 +1,42 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type GroupDisbandLogic struct {
ctx context.Context
svc *service.Service
}
func NewGroupDisbandLogic(ctx context.Context, svc *service.Service) *GroupDisbandLogic {
return &GroupDisbandLogic{
ctx: ctx,
svc: svc,
}
}
// GroupDisband 解散群
func (l *GroupDisbandLogic) GroupDisband(req *pb.GroupDisbandReq) (*pb.GroupDisbandResp, error) {
groupId := req.GroupId
personId := req.PersonId
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
// 只有群主可以解散群
if err = person.IsOwner(); err != nil {
return nil, err
}
err = l.svc.GroupDisband(l.ctx, groupId, personId)
if err != nil {
return nil, err
}
return &pb.GroupDisbandResp{}, nil
}

View File

@@ -0,0 +1,47 @@
package logic
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type GroupExitLogic struct {
ctx context.Context
svc *service.Service
}
func NewGroupExitLogic(ctx context.Context, svc *service.Service) *GroupExitLogic {
return &GroupExitLogic{
ctx: ctx,
svc: svc,
}
}
// GroupExit 退出群
func (l *GroupExitLogic) GroupExit(req *pb.GroupExitReq) (*pb.GroupExitResp, error) {
groupId := req.GroupId
personId := req.PersonId
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsOwner(); err == nil {
return nil, xerror.NewError(xerror.GroupOwnerExit)
}
err = l.svc.ExitGroup(l.ctx, group, person)
if err != nil {
return nil, err
}
return &pb.GroupExitResp{}, nil
}

View File

@@ -0,0 +1,69 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type GroupRemoveLogic struct {
ctx context.Context
svc *service.Service
}
func NewGroupRemoveLogic(ctx context.Context, svc *service.Service) *GroupRemoveLogic {
return &GroupRemoveLogic{
ctx: ctx,
svc: svc,
}
}
// GroupRemove 踢人
func (l *GroupRemoveLogic) GroupRemove(req *pb.GroupRemoveReq) (*pb.GroupRemoveResp, error) {
groupId := req.GroupId
memberIds := req.MemberIds
personId := req.PersonId
// 判断一下该群是否存在
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
// 判断踢人者权限
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
// 过滤可以踢人的列表
needDeleteMembers := l.svc.GetFilteredGroupMembers(l.ctx, group, FilteredMemberIds(memberIds))
if len(needDeleteMembers) == 0 {
return &pb.GroupRemoveResp{MemberNum: group.GroupMemberNum}, nil
}
canRemoveMemberIds := make([]string, 0)
canRemoveMembers := make([]*biz.GroupMember, 0)
for _, member := range needDeleteMembers {
if err := person.RemoveOneMember(member); err != nil {
return nil, err
}
canRemoveMemberIds = append(canRemoveMemberIds, member.GroupMemberId)
canRemoveMembers = append(canRemoveMembers, member)
}
// 执行踢人
if err = l.svc.RemoveGroupMembers(l.ctx, group, canRemoveMembers); err != nil {
return nil, err
}
return &pb.GroupRemoveResp{
MemberNum: group.GroupMemberNum - int32(len(canRemoveMemberIds)),
MemberIds: canRemoveMemberIds,
}, nil
}

View File

@@ -0,0 +1,60 @@
package logic
import (
"context"
"github.com/rs/zerolog"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type ChangeOwnerLogic struct {
ctx context.Context
svc *service.Service
log zerolog.Logger
}
func NewChangeOwnerLogic(ctx context.Context, svc *service.Service) *ChangeOwnerLogic {
return &ChangeOwnerLogic{
ctx: ctx,
svc: svc,
log: svc.GetLog(),
}
}
func (l *ChangeOwnerLogic) ChangeOwner(req *types.ChangeOwnerRequest) (res *types.ChangeOwnerResponse, err error) {
groupId := req.Id
personId := req.PersonId
memberId := req.MemberId
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
member, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, memberId, groupId)
if err != nil {
return nil, err
}
// 只有群主可以转让群
if err = person.IsOwner(); err != nil {
return nil, err
}
if personId == memberId {
return nil, xerror.NewError(xerror.GroupChangeOwnerSelf)
}
err = l.svc.ChangeOwner(l.ctx, group, person, member)
if err != nil {
return nil, err
}
return res, nil
}

View File

@@ -0,0 +1,68 @@
package logic
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type InviteGroupMembersLogic struct {
ctx context.Context
svc *service.Service
}
func NewInviteGroupMembersLogic(ctx context.Context, svc *service.Service) *InviteGroupMembersLogic {
return &InviteGroupMembersLogic{
ctx: ctx,
svc: svc,
}
}
// InviteGroupMembers 邀请新成员
func (l *InviteGroupMembersLogic) InviteGroupMembers(req *pb.InviteGroupMembersReq) (*pb.InviteGroupMembersResp, error) {
//personId := req.Inviter.MemberId
groupId := req.GroupId
inviterId := req.InviterId
newMemberIds := FilteredMemberIds(req.MemberIds)
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
if inviterId == "" {
switch group.GroupJoinType {
case biz.GroupJoinTypeAny:
err = l.svc.InviteMembers(l.ctx, group, newMemberIds)
if err != nil {
return nil, err
}
return &pb.InviteGroupMembersResp{}, nil
default:
return nil, xerror.NewError(xerror.GroupInvitePermissionDenied)
}
}
// 得到邀请人信息
inviter, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, inviterId, groupId)
if err != nil {
return nil, err
}
switch inviter.TryInvite(group) {
case biz.InviteOk:
err = l.svc.InviteMembers(l.ctx, group, newMemberIds)
if err != nil {
return nil, err
}
return &pb.InviteGroupMembersResp{}, nil
case biz.InviteApply:
return nil, xerror.NewError(xerror.GroupInvitePermissionDenied)
case biz.InviteFail:
return nil, xerror.NewError(xerror.GroupInvitePermissionDenied)
default:
return nil, xerror.NewError(xerror.GroupInvitePermissionDenied)
}
}

View File

@@ -0,0 +1,60 @@
package logic
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type SetAdminLogic struct {
ctx context.Context
svc *service.Service
}
func NewSetAdminLogic(ctx context.Context, svc *service.Service) *SetAdminLogic {
return &SetAdminLogic{
ctx: ctx,
svc: svc,
}
}
// SetAdmin 设置管理员
func (l *SetAdminLogic) SetAdmin(req *pb.SetAdminReq) (*pb.SetAdminResp, error) {
groupId := req.GroupId
personId := req.PersonId
memberId := req.MemberId
memberType := int32(req.GroupMemberType)
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
// 只有群主可以设置管理员
if personId != group.GroupOwnerId || person.GroupMemberType != biz.GroupMemberTypeOwner || memberId == personId {
err = xerror.NewError(xerror.GroupOwnerSetAdmin)
return nil, err
}
member, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, memberId, groupId)
if err != nil {
return nil, err
}
if err = group.TrySetAdmin(); memberType == biz.GroupMemberTypeAdmin && err != nil {
return nil, err
}
err = l.svc.SetAdmin(l.ctx, group, member, memberType)
if err != nil {
return nil, err
}
return &pb.SetAdminResp{}, nil
}

View File

@@ -0,0 +1,45 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type UpdateGroupAvatarLogic struct {
ctx context.Context
svc *service.Service
}
func NewUpdateGroupAvatarLogic(ctx context.Context, svc *service.Service) *UpdateGroupAvatarLogic {
return &UpdateGroupAvatarLogic{
ctx: ctx,
svc: svc,
}
}
// UpdateGroupAvatar 更新群头像
func (l *UpdateGroupAvatarLogic) UpdateGroupAvatar(req *pb.UpdateGroupAvatarReq) (*pb.UpdateGroupAvatarResp, error) {
groupId := req.GroupId
personId := req.PersonId
groupAvatar := req.Avatar
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := l.svc.UpdateGroupAvatar(l.ctx, group, groupAvatar); err != nil {
return nil, err
}
return &pb.UpdateGroupAvatarResp{}, nil
}

View File

@@ -0,0 +1,44 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type UpdateGroupFriendTypeLogic struct {
ctx context.Context
svc *service.Service
}
func NewUpdateGroupFriendTypeLogic(ctx context.Context, svc *service.Service) *UpdateGroupFriendTypeLogic {
return &UpdateGroupFriendTypeLogic{
ctx: ctx,
svc: svc,
}
}
// UpdateGroupFriendType 更新群内加好友设置
func (l *UpdateGroupFriendTypeLogic) UpdateGroupFriendType(req *pb.UpdateGroupFriendTypeReq) (*pb.UpdateGroupFriendTypeResp, error) {
groupId := req.GroupId
personId := req.PersonId
friendType := int32(req.GroupFriendType)
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := l.svc.UpdateGroupFriendType(l.ctx, group, friendType); err != nil {
return nil, err
}
return &pb.UpdateGroupFriendTypeResp{}, nil
}

View File

@@ -0,0 +1,45 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type UpdateGroupJoinTypeLogic struct {
ctx context.Context
svc *service.Service
}
func NewUpdateGroupJoinTypeLogic(ctx context.Context, svc *service.Service) *UpdateGroupJoinTypeLogic {
return &UpdateGroupJoinTypeLogic{
ctx: ctx,
svc: svc,
}
}
// UpdateGroupJoinType 更新加群设置
func (l *UpdateGroupJoinTypeLogic) UpdateGroupJoinType(req *pb.UpdateGroupJoinTypeReq) (*pb.UpdateGroupJoinTypeResp, error) {
groupId := req.GroupId
personId := req.PersonId
joinType := int32(req.GroupJoinType)
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := l.svc.UpdateGroupJoinType(l.ctx, group, joinType); err != nil {
return nil, err
}
return &pb.UpdateGroupJoinTypeResp{}, nil
}

View File

@@ -0,0 +1,65 @@
package logic
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type UpdateGroupMemberMuteTimeLogic struct {
ctx context.Context
svc *service.Service
}
func NewUpdateGroupMemberMuteTimeLogic(ctx context.Context, svc *service.Service) *UpdateGroupMemberMuteTimeLogic {
return &UpdateGroupMemberMuteTimeLogic{
ctx: ctx,
svc: svc,
}
}
// UpdateGroupMemberMuteTime 更新群成员禁言时间
func (l *UpdateGroupMemberMuteTimeLogic) UpdateGroupMemberMuteTime(req *pb.UpdateGroupMemberMuteTimeReq) (*pb.UpdateGroupMemberMuteTimeResp, error) {
groupId := req.GroupId
memberIds := req.MemberIds
personId := req.PersonId
muteTime := req.MuteTime
var members []*biz.GroupMember
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
// 过滤
for _, memberId := range memberIds {
member, err := l.svc.GetMemberByMemberIdAndGroupId(l.ctx, memberId, groupId)
if err != nil {
return nil, err
}
if err := member.IsAdmin(); err == nil {
return nil, xerror.NewError(xerror.GroupMutePermission)
}
members = append(members, member)
}
members, err = l.svc.UpdateMembersMuteTime(l.ctx, group, members, muteTime)
if err != nil {
return nil, err
}
return &pb.UpdateGroupMemberMuteTimeResp{
Members: NewRPCGroupMemberInfos(members),
}, nil
}

View File

@@ -0,0 +1,42 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type UpdateGroupMemberNameLogic struct {
ctx context.Context
svc *service.Service
}
func NewUpdateGroupMemberNameLogic(ctx context.Context, svc *service.Service) *UpdateGroupMemberNameLogic {
return &UpdateGroupMemberNameLogic{
ctx: ctx,
svc: svc,
}
}
// UpdateGroupMemberName 更新群成员群昵称
func (l *UpdateGroupMemberNameLogic) UpdateGroupMemberName(req *pb.UpdateGroupMemberNameReq) (*pb.UpdateGroupMemberNameResp, error) {
groupId := req.GroupId
personId := req.PersonId
memberName := req.MemberName
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err := l.svc.UpdateMemberName(l.ctx, group, person, memberName); err != nil {
return nil, err
}
return &pb.UpdateGroupMemberNameResp{}, nil
}

View File

@@ -0,0 +1,45 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type UpdateGroupMuteTypeLogic struct {
ctx context.Context
svc *service.Service
}
func NewUpdateGroupMuteTypeLogic(ctx context.Context, svc *service.Service) *UpdateGroupMuteTypeLogic {
return &UpdateGroupMuteTypeLogic{
ctx: ctx,
svc: svc,
}
}
// UpdateGroupMuteType 更新群内禁言设置
func (l *UpdateGroupMuteTypeLogic) UpdateGroupMuteType(req *pb.UpdateGroupMuteTypeReq) (*pb.UpdateGroupMuteTypeResp, error) {
groupId := req.GroupId
personId := req.PersonId
muteType := int32(req.GroupMuteType)
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := l.svc.UpdateGroupMuteType(l.ctx, group, muteType); err != nil {
return nil, err
}
return &pb.UpdateGroupMuteTypeResp{}, nil
}

View File

@@ -0,0 +1,46 @@
package logic
import (
"context"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
type UpdateGroupNameLogic struct {
ctx context.Context
svc *service.Service
}
func NewUpdateGroupNameLogic(ctx context.Context, svc *service.Service) *UpdateGroupNameLogic {
return &UpdateGroupNameLogic{
ctx: ctx,
svc: svc,
}
}
// UpdateGroupName 更新群名称
func (l *UpdateGroupNameLogic) UpdateGroupName(req *pb.UpdateGroupNameReq) (*pb.UpdateGroupNameResp, error) {
groupId := req.GroupId
personId := req.PersonId
groupName := req.Name
groupPubName := req.PublicName
group, err := l.svc.GetGroupInfoByGroupId(l.ctx, groupId)
if err != nil {
return nil, err
}
person, err := l.svc.GetPersonByMemberIdAndGroupId(l.ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := l.svc.UpdateGroupName(l.ctx, group, groupName, groupPubName); err != nil {
return nil, err
}
return &pb.UpdateGroupNameResp{}, nil
}

View File

@@ -0,0 +1,94 @@
package logic
import (
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"strings"
)
func FilteredMemberIds(memberIds []string) []string {
newMemberIds := make([]string, 0, len(memberIds))
for _, memberId := range memberIds {
memberId, err := FilteredMemberId(memberId)
if err != nil {
continue
}
newMemberIds = append(newMemberIds, memberId)
}
return newMemberIds
}
func FilteredMemberId(memberId string) (string, error) {
memberId = strings.TrimSpace(memberId)
if memberId != "" && len(memberId) < 40 {
return memberId, nil
}
return "", xerror.NewError(xerror.ParamsError)
}
func NewRPCGroupInfo(do *biz.GroupInfo) *pb.GroupBizInfo {
if do == nil {
return &pb.GroupBizInfo{}
}
return &pb.GroupBizInfo{
Id: do.GroupId,
MarkId: do.GroupMarkId,
Name: do.GroupName,
Avatar: do.GroupAvatar,
MemberNum: do.GroupMemberNum,
MemberMaximum: do.GroupMaximum,
Introduce: do.GroupIntroduce,
Status: pb.GroupStatus(do.GroupStatus),
OwnerId: do.GroupOwnerId,
CreateTime: do.GroupCreateTime,
UpdateTime: do.GroupUpdateTime,
JoinType: pb.GroupJoinType(do.GroupJoinType),
MuteType: pb.GroupMuteType(do.GroupMuteType),
FriendType: pb.GroupFriendType(do.GroupFriendType),
MuteNum: do.MuteNum,
AdminNum: do.AdminNum,
AESKey: do.AESKey,
PubName: do.GroupPubName,
Type: pb.GroupType(do.GroupType),
Owner: nil,
Person: nil,
Members: nil,
}
}
func NewRPCGroupInfos(dos []*biz.GroupInfo) []*pb.GroupBizInfo {
dtos := make([]*pb.GroupBizInfo, 0, len(dos))
for _, do := range dos {
dtos = append(dtos, NewRPCGroupInfo(do))
}
return dtos
}
func NewRPCGroupMemberInfo(do *biz.GroupMember) *pb.GroupMemberBizInfo {
if do == nil {
return &pb.GroupMemberBizInfo{}
}
return &pb.GroupMemberBizInfo{
GroupId: do.GroupId,
Id: do.GroupMemberId,
Name: do.GroupMemberName,
Type: pb.GroupMemberType(do.GroupMemberType),
MuteTime: do.GroupMemberMuteTime,
JoinTime: do.GroupMemberJoinTime,
}
}
func NewRPCGroupMemberInfos(dos []*biz.GroupMember) []*pb.GroupMemberBizInfo {
dtos := make([]*pb.GroupMemberBizInfo, 0, len(dos))
for _, do := range dos {
dtos = append(dtos, NewRPCGroupMemberInfo(do))
}
return dtos
}

View File

@@ -0,0 +1,12 @@
package biz
const (
DisPlayNum = 10 // 查看群信息默认显示的人数
MuteMaximum = int64(^uint(0) >> 1) // 永久禁言的时间 9223372036854775807
)
var (
GroupMaximum int32 = 2000
AdminNum int32 = 10
)

View File

@@ -0,0 +1,61 @@
package biz
import (
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
const (
GroupApplyWait = 0
GroupApplyAccept = 1
GroupApplyReject = 2
GroupApplyIgnore = 10
)
type GroupApplyBiz struct {
// 审批 ID
ApplyId int64
// 群 ID
GroupId int64
// 邀请人 ID, 空表示是自己主动申请的
InviterId string
// 申请加入人 ID
MemberId string
// 申请备注
ApplyNote string
// 审批人 ID
OperatorId string
// 审批情况 0=待审批, 1=审批通过, 2=审批不通过, 10=审批忽略
ApplyStatus int32
// 拒绝原因
RejectReason string
// 创建时间 ms
CreateTime int64
// 修改时间 ms
UpdateTime int64
}
// ToTypes 将业务模型转换为 api 展示信息
func (g *GroupApplyBiz) ToTypes() *types.GroupApplyInfo {
return &types.GroupApplyInfo{
ApplyId: convert.ToString(g.ApplyId),
GroupId: convert.ToString(g.GroupId),
InviterId: g.InviterId,
MemberId: g.MemberId,
ApplyNote: g.ApplyNote,
OperatorId: g.OperatorId,
ApplyStatus: g.ApplyStatus,
RejectReason: g.RejectReason,
CreateTime: g.CreateTime,
UpdateTime: g.UpdateTime,
}
}
// IsWait 判断该审批是否被处理过
func (g *GroupApplyBiz) IsWait() error {
if g.ApplyStatus == GroupApplyWait {
return nil
}
return xerror.NewError(xerror.GroupApplyUsed)
}

View File

@@ -0,0 +1,145 @@
package biz
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
type groupContextKey string
const (
// GroupContextKey .
GroupContextKey = groupContextKey("FZM-Group-Token")
GroupIdContextKey = groupContextKey("FZM-Group-Id")
)
const (
GroupStatusNormal = 0 // 正常
GroupStatusBlock = 1 // 封禁
GroupStatusDisBand = 2 // 解散
GroupJoinTypeAny = 0 // 无需审批(默认)
GroupJoinTypeAdmin = 1 // 禁止加群,群主和管理员邀请加群
GroupJoinTypeApply = 2 // 普通人邀请需要审批,群主和管理员直接加群
GroupMuteTypeAny = 0 // 全员可发言
GroupMuteTypeAdmin = 1 // 全员禁言(除群主和管理员)
GroupFriendTypeAllow = 0 // 群内可加好友
GroupFriendTypeDeny = 1 // 群内禁止加好友
// 群类型
GroupTypeNormal = 0 // 普通群
GroupTypeEnt = 1 // 全员群
GroupTypeDep = 2 // 部门群
)
type GroupInfo struct {
GroupId int64
GroupMarkId string
GroupName string
GroupAvatar string
// 群人数
GroupMemberNum int32
// 群人数上限
GroupMaximum int32
GroupIntroduce string
// 群状态0=正常 1=封禁 2=解散
GroupStatus int32
GroupOwnerId string
GroupCreateTime int64
GroupUpdateTime int64
// 加群方式0=无需审批默认1=禁止加群,群主和管理员邀请加群, 2=普通人邀请需要审批,群主和管理员直接加群
GroupJoinType int32
// 禁言, 0=全员可发言, 1=全员禁言(除群主和管理员)
GroupMuteType int32
// 加好友限制, 0=群内可加好友1=群内禁止加好友
GroupFriendType int32
// 群内当前被禁言的人数
MuteNum int32 `json:"muteNum"`
// 群内管理员数量
AdminNum int32 `json:"adminNum"`
//
AESKey string
//
GroupPubName string
// 群类型 (0: 普通群, 1: 全员群, 2: 部门群)
GroupType int32
}
func (g *GroupInfo) IsNormal() error {
switch g.GroupStatus {
case GroupStatusNormal:
return nil
case GroupStatusBlock:
return xerror.NewError(xerror.GroupStatusBlock)
case GroupStatusDisBand:
return xerror.NewError(xerror.GroupStatusDisBand)
default:
return xerror.NewError(xerror.CodeInnerError)
}
}
func (g *GroupInfo) ToTypes(owner *types.GroupMember, person *types.GroupMember) *types.GroupInfo {
return &types.GroupInfo{
Id: g.GroupId,
IdStr: convert.ToString(g.GroupId),
MarkId: g.GroupMarkId,
Name: g.GroupName,
Avatar: g.GroupAvatar,
Introduce: g.GroupIntroduce,
Owner: owner,
Person: person,
MemberNum: g.GroupMemberNum,
Maximum: g.GroupMaximum,
Status: g.GroupStatus,
CreateTime: g.GroupCreateTime,
JoinType: g.GroupJoinType,
MuteType: g.GroupMuteType,
FriendType: g.GroupFriendType,
MuteNum: g.MuteNum,
AdminNum: g.AdminNum,
AESKey: g.AESKey,
PublicName: g.GroupPubName,
GroupType: g.GroupType,
}
}
func (g *GroupInfo) TryJoin(add int32) error {
if add+g.GroupMemberNum > g.GroupMaximum {
return xerror.NewError(xerror.GroupMemberLimit)
}
return nil
}
func (g *GroupInfo) TrySetAdmin() error {
if g.AdminNum+1 > AdminNum {
return xerror.NewError(xerror.GroupAdminNumLimit)
}
return nil
}
func (g *GroupInfo) WithContext(ctx context.Context) context.Context {
return context.WithValue(ctx, GroupContextKey, g)
}
func NewGroupInfoFromContext(ctx context.Context) (*GroupInfo, error) {
if group, ok := ctx.Value(GroupContextKey).(*GroupInfo); ok {
return group, nil
}
return nil, xerror.NewError(xerror.GroupNotExist)
}
func NewGroupIdFromContext(ctx context.Context) (int64, error) {
if groupId, ok := ctx.Value(GroupIdContextKey).(int64); ok {
return groupId, nil
}
return 0, xerror.NewError(xerror.GroupNotExist)
}

View File

@@ -0,0 +1,105 @@
package biz
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
type groupMemberContextKey string
const (
// GroupMemberContextKey .
GroupMemberContextKey = groupMemberContextKey("FZM-Group-Member-Token")
)
const (
GroupMemberTypeOwner = 2 // 群主
GroupMemberTypeAdmin = 1 // 管理员
GroupMemberTypeNormal = 0 // 群员
GroupMemberTypeOther = 10 // 退群
)
type GroupMember struct {
GroupId int64
GroupMemberId string
GroupMemberName string
// 用户角色0=群员,1=管理员, 2=群主10=退群
GroupMemberType int32
// 该用户被禁言结束的时间 9223372036854775807=永久禁言
GroupMemberMuteTime int64
GroupMemberJoinTime int64
}
func (m *GroupMember) ToTypes() *types.GroupMember {
return &types.GroupMember{
MemberId: m.GroupMemberId,
MemberName: m.GroupMemberName,
MemberType: m.GroupMemberType,
MemberMuteTime: m.GroupMemberMuteTime,
}
}
func (m *GroupMember) IsAdmin() error {
if m.GroupMemberType < GroupMemberTypeAdmin {
return xerror.NewError(xerror.GroupAdminDeny)
}
return nil
}
func (m *GroupMember) IsOwner() error {
if m.GroupMemberType < GroupMemberTypeOwner {
return xerror.NewError(xerror.GroupOwnerDeny)
}
return nil
}
func (m *GroupMember) RemoveOneMember(member *GroupMember) error {
if m.GroupId != member.GroupId || m.GroupMemberType == GroupMemberTypeOther || member.GroupMemberType == GroupMemberTypeOwner {
return xerror.NewError(xerror.CodeInnerError)
}
if m.GroupMemberType <= member.GroupMemberType {
return xerror.NewError(xerror.GroupHigherPermission)
}
return nil
}
type InviteFlow int
const (
InviteOk InviteFlow = 1
InviteApply InviteFlow = 2
InviteFail InviteFlow = 3
)
func (m *GroupMember) TryInvite(group *GroupInfo) InviteFlow {
if m.GroupMemberType == GroupMemberTypeNormal {
switch group.GroupJoinType {
case GroupJoinTypeApply:
return InviteApply
case GroupJoinTypeAny:
return InviteOk
case GroupJoinTypeAdmin:
return InviteFail
default:
return InviteFail
}
}
return InviteOk
}
func (m *GroupMember) WithContext(ctx context.Context) context.Context {
return context.WithValue(ctx, GroupMemberContextKey, m)
}
func NewGroupMemberFromContext(ctx context.Context) (*GroupMember, error) {
if groupMember, ok := ctx.Value(GroupMemberContextKey).(*GroupMember); ok {
return groupMember, nil
}
return nil, xerror.NewError(xerror.GroupPersonNotExist)
}

View File

@@ -0,0 +1,8 @@
package db
import "errors"
var (
ErrGroupNotExist = errors.New("the group is not exist")
ErrGroupMemberNotExist = errors.New("the member is not exist")
)

View File

@@ -0,0 +1,59 @@
package db
import (
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/utils/go-kit/convert"
)
type GroupApply struct {
// 审批 ID
Id int64
// 群 ID
GroupId int64
// 邀请人 ID, 空表示是自己主动申请的
InviterId string
// 申请加入人 ID
MemberId string
// 申请备注
ApplyNote string
// 审批人 ID
OperatorId string
// 审批情况 0=待审批, 1=审批通过, 2=审批不通过, 10=审批忽略
ApplyStatus int32
// 拒绝原因
RejectReason string
// 创建时间 ms
CreateTime int64
// 修改时间 ms
UpdateTime int64
}
func ConvertGroupApply(res map[string]string) *GroupApply {
return &GroupApply{
Id: convert.ToInt64(res["id"]),
GroupId: convert.ToInt64(res["group_id"]),
InviterId: convert.ToString(res["inviter_id"]),
MemberId: convert.ToString(res["member_id"]),
ApplyNote: convert.ToString(res["apply_note"]),
OperatorId: convert.ToString(res["operator_id"]),
ApplyStatus: convert.ToInt32(res["apply_status"]),
RejectReason: convert.ToString(res["reject_reason"]),
CreateTime: convert.ToInt64(res["create_time"]),
UpdateTime: convert.ToInt64(res["update_time"]),
}
}
func (a *GroupApply) ToBiz() *biz.GroupApplyBiz {
return &biz.GroupApplyBiz{
ApplyId: a.Id,
GroupId: a.GroupId,
InviterId: a.InviterId,
MemberId: a.MemberId,
ApplyNote: a.ApplyNote,
OperatorId: a.OperatorId,
ApplyStatus: a.ApplyStatus,
RejectReason: a.RejectReason,
CreateTime: a.CreateTime,
UpdateTime: a.UpdateTime,
}
}

View File

@@ -0,0 +1,90 @@
package db
import (
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/utils/go-kit/convert"
)
type GroupInfo struct {
GroupId int64 `json:"groupId" form:"groupId"`
GroupMarkId string `json:"groupMarkId" form:"groupMarkId"`
GroupName string `json:"groupName" form:"groupName"`
GroupAvatar string `json:"groupAvatar" form:"groupAvatar"`
// 群人数
GroupMemberNum int32 `json:"groupMemberNum" form:"groupMemberNum"`
// 群人数上限
GroupMaximum int32 `json:"groupMaximum" form:"groupMaximum"`
GroupIntroduce string `json:"groupIntroduce" form:"groupIntroduce"`
// 群状态0=正常 1=封禁 2=解散
GroupStatus int32 `json:"groupStatus" form:"groupStatus"`
GroupOwnerId string `json:"groupOwnerId" form:"groupOwnerId"`
GroupCreateTime int64 `json:"groupCreateTime" form:"groupCreateTime"`
GroupUpdateTime int64 `json:"groupUpdateTime" form:"groupUpdateTime"`
// 加群方式0=无需审批默认1=禁止加群,群主和管理员邀请加群, 2=普通人邀请需要审批,群主和管理员直接加群
GroupJoinType int32 `json:"groupJoinType" form:"groupJoinType"`
// 禁言, 0=全员可发言, 1=全员禁言(除群主和管理员)
GroupMuteType int32 `json:"groupMuteType" form:"groupMuteType"`
// 加好友限制, 0=群内可加好友1=群内禁止加好友
GroupFriendType int32
//
GroupAESKey string
//
GroupPubName string
// 群类型 (0: 普通群, 1: 全员群, 2: 部门群)
GroupType int32
}
func ConvertGroupInfos(maps []map[string]string) []*GroupInfo {
dtos := make([]*GroupInfo, 0, len(maps))
for _, res := range maps {
dtos = append(dtos, ConvertGroupInfo(res))
}
return dtos
}
func ConvertGroupInfo(res map[string]string) *GroupInfo {
return &GroupInfo{
GroupId: convert.ToInt64(res["group_id"]),
GroupMarkId: res["group_mark_id"],
GroupName: res["group_name"],
GroupAvatar: res["group_avatar"],
GroupMemberNum: convert.ToInt32(res["group_member_num"]),
GroupMaximum: convert.ToInt32(res["group_maximum"]),
GroupIntroduce: res["group_Introduce"],
GroupStatus: convert.ToInt32(res["group_status"]),
GroupOwnerId: res["group_owner_id"],
GroupCreateTime: convert.ToInt64(res["group_create_time"]),
GroupUpdateTime: convert.ToInt64(res["group_update_time"]),
GroupJoinType: convert.ToInt32(res["group_join_type"]),
GroupMuteType: convert.ToInt32(res["group_mute_type"]),
GroupFriendType: convert.ToInt32(res["group_friend_type"]),
GroupAESKey: convert.ToString(res["group_aes_key"]),
GroupPubName: convert.ToString(res["group_pub_name"]),
GroupType: convert.ToInt32(res["group_type"]),
}
}
func (g *GroupInfo) ToBiz() *biz.GroupInfo {
return &biz.GroupInfo{
GroupId: g.GroupId,
GroupMarkId: g.GroupMarkId,
GroupName: g.GroupName,
GroupAvatar: g.GroupAvatar,
GroupMemberNum: g.GroupMemberNum,
GroupMaximum: g.GroupMaximum,
GroupIntroduce: g.GroupIntroduce,
GroupStatus: g.GroupStatus,
GroupOwnerId: g.GroupOwnerId,
GroupCreateTime: g.GroupCreateTime,
GroupUpdateTime: g.GroupUpdateTime,
GroupJoinType: g.GroupJoinType,
GroupMuteType: g.GroupMuteType,
GroupFriendType: g.GroupFriendType,
MuteNum: 0,
AdminNum: 0,
AESKey: g.GroupAESKey,
GroupPubName: g.GroupPubName,
GroupType: g.GroupType,
}
}

View File

@@ -0,0 +1,89 @@
package db
import (
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/utils/go-kit/convert"
)
type GroupMember struct {
GroupId int64 `json:"groupId" form:"groupId"`
GroupMemberId string `json:"groupMemberId" form:"groupMemberId"`
GroupMemberName string `json:"groupMemberName" form:"groupMemberName"`
// 用户角色2=群主1=管理员0=群员10=退群
GroupMemberType int32 `json:"groupMemberType" form:"groupMemberType"`
GroupMemberJoinTime int64 `json:"groupMemberJoinTime" form:"groupMemberJoinTime"`
GroupMemberUpdateTime int64 `json:"groupMemberUpdateTime" form:"groupMemberUpdateTime"`
}
func ConvertGroupMember(res map[string]string) *GroupMember {
return &GroupMember{
GroupId: convert.ToInt64(res["group_id"]),
GroupMemberId: res["group_member_id"],
GroupMemberName: res["group_member_name"],
GroupMemberType: convert.ToInt32(res["group_member_type"]),
GroupMemberJoinTime: convert.ToInt64(res["group_member_join_time"]),
//GroupMemberUpdateTime: convert.ToInt64(res["group_member_update_time"]),
}
}
func (m *GroupMember) ToBiz() *biz.GroupMember {
return &biz.GroupMember{
GroupId: m.GroupId,
GroupMemberId: m.GroupMemberId,
GroupMemberName: m.GroupMemberName,
GroupMemberType: m.GroupMemberType,
GroupMemberMuteTime: 0,
GroupMemberJoinTime: m.GroupMemberJoinTime,
}
}
type GroupMemberMute struct {
GroupId int64
GroupMemberId string
// 该用户被禁言结束的时间 9223372036854775807=永久禁言
GroupMemberMuteTime int64
GroupMemberMuteUpdateTime int64
}
func ConvertGroupMemberMute(res map[string]string) *GroupMemberMute {
return &GroupMemberMute{
GroupId: convert.ToInt64(res["group_id"]),
GroupMemberId: res["group_member_id"],
GroupMemberMuteTime: convert.ToInt64(res["group_member_mute_time"]),
GroupMemberMuteUpdateTime: convert.ToInt64(res["group_member_mute_update_time"]),
}
}
type GroupMemberWithMute struct {
GroupId int64
GroupMemberId string
GroupMemberName string
GroupMemberType int32
GroupMemberMuteTime int64
GroupMemberJoinTime int64
}
func ConvertGroupMemberWithMute(res map[string]string) *GroupMemberWithMute {
if res["group_member_mute_time"] == "" {
res["group_member_mute_time"] = "0"
}
return &GroupMemberWithMute{
GroupId: convert.ToInt64(res["group_id"]),
GroupMemberId: res["group_member_id"],
GroupMemberMuteTime: convert.ToInt64(res["group_member_mute_time"]),
GroupMemberName: res["group_member_name"],
GroupMemberType: convert.ToInt32(res["group_member_type"]),
GroupMemberJoinTime: convert.ToInt64(res["group_member_join_time"]),
}
}
func (m *GroupMemberWithMute) ToBiz() *biz.GroupMember {
return &biz.GroupMember{
GroupId: m.GroupId,
GroupMemberId: m.GroupMemberId,
GroupMemberName: m.GroupMemberName,
GroupMemberType: m.GroupMemberType,
GroupMemberMuteTime: m.GroupMemberMuteTime,
GroupMemberJoinTime: m.GroupMemberJoinTime,
}
}

View File

@@ -0,0 +1,17 @@
package model
import (
"github.com/pkg/errors"
)
var (
//ErrAdminPermission = errors.New("需要更高的权限")
//ErrGroupIdNotExist = errors.New("该群号不存在")
ErrMemberNotExist = errors.New("该用户不在本群中")
//ErrPersonNotExist = errors.New("你已不在本群中")
ErrType = errors.New("参数不存在")
//ErrAdminNum = errors.New("管理员数量已满")
ErrPushMsgArg = errors.New("rpc error: code = Unknown desc = rpc pushmsg arg error")
ErrRecordNotExist = errors.New("record not exist.")
)

View File

@@ -0,0 +1,433 @@
package types
type GeneralResponse struct {
Result int `json:"result"`
Message int `json:"message"`
Data interface{} `json:"data"`
}
type GroupMember struct {
// 用户 ID
MemberId string `json:"memberId" form:"memberId"`
// 用户群昵称
MemberName string `json:"memberName" form:"memberName"`
// 用户角色2=群主1=管理员0=群员10=退群
MemberType int32 `json:"memberType" form:"memberType"`
// 该用户被禁言结束的时间 9223372036854775807=永久禁言
MemberMuteTime int64 `json:"memberMuteTime"`
}
type GroupInfo struct {
// 群 ID
Id int64 `json:"id" form:"id"`
IdStr string `json:"idStr"`
// 群显示的 ID
MarkId string `json:"markId" form:"markId"`
// 群名称 加密的
Name string `json:"name" form:"name"`
// 公开的群名称 不加密的
PublicName string `json:"publicName"`
// 头像 url
Avatar string `json:"avatar" form:"avatar"`
Introduce string `json:"introduce" form:"introduce"`
// 群主 信息
Owner *GroupMember `json:"owner" form:"owner"`
// 本人在群内的信息
Person *GroupMember `json:"person" form:"person"`
// 群人数
MemberNum int32 `json:"memberNum" form:"memberNum"`
// 群人数上限
Maximum int32 `json:"maximum" form:"maximum"`
// 群状态0=正常 1=封禁 2=解散
Status int32 `json:"status" form:"status"`
// 群创建时间
CreateTime int64 `json:"createTime" form:"createTime"`
// 加群方式0=无需审批默认1=禁止加群,群主和管理员邀请加群, 2=普通人邀请需要审批,群主和管理员直接加群
JoinType int32 `json:"joinType" form:"joinType"`
// 禁言, 0=全员可发言, 1=全员禁言(除群主和管理员)
MuteType int32 `json:"muteType" form:"muteType"`
// 加好友限制, 0=群内可加好友1=群内禁止加好友
FriendType int32 `json:"friendType"`
// 群内当前被禁言的人数
MuteNum int32 `json:"muteNum"`
// 群内管理员数量
AdminNum int32 `json:"adminNum"`
//
AESKey string `json:"key"`
// 群类型 (0: 普通群, 1: 全员群, 2: 部门群)
GroupType int32 `json:"groupType"`
}
type CreateGroupRequest struct {
Name string `json:"name" form:"name"`
Avatar string `json:"avatar" form:"avatar"`
Introduce string `json:"introduce" form:"introduce"`
MemberIds []string `json:"memberIds" form:"memberIds"`
Owner GroupMember `json:"-"`
Members []GroupMember `json:"-"`
}
type CreateGroupResponse struct {
*GroupInfo
// 群成员
Members []GroupMember `json:"members" form:"members"`
}
type InviteGroupMembersRequest struct {
Id int64 `json:"id" form:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
Inviter GroupMember `json:"-"`
NewMembers []GroupMember `json:"-"`
NewMemberIds []string `json:"newMemberIds" form:"newMemberIds" binding:"required"`
}
type InviteGroupMembersResponse struct {
Id int64 `json:"id" form:"id" example:"123821199217135616"`
IdStr string `json:"idStr"`
MemberNum int32 `json:"memberNum" form:"memberNum" example:"5"`
//Inviter GroupMember `json:"inviter" form:"inviter"`
//NewMembers []GroupMember `json:"newMembers" form:"newMembers"`
}
type GetGroupInfoRequest struct {
Id int64 `json:"id" uri:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
DisPlayNum int64 `json:"-"`
}
type GetGroupInfoResponse struct {
*GroupInfo
Members []*GroupMember `json:"members" form:"members"`
}
type GetGroupListRequest struct {
PersonId string `json:"-"`
}
type GetGroupListResponse struct {
Groups []*GroupInfo `json:"groups"`
}
type GetGroupMemberListRequest struct {
Id int64 `json:"id" uri:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
}
type GetGroupMemberListResponse struct {
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
Members []*GroupMember `json:"members"`
}
type GetGroupMemberInfoRequest struct {
Id int64 `json:"id" uri:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
MemberId string `json:"memberId" uri:"memberId" binding:"required"`
PersonId string `json:"-"`
}
type GetGroupMemberInfoResponse struct {
*GroupMember
}
type GroupExitRequest struct {
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
}
type GroupExitResponse struct {
}
type GroupRemoveRequest struct {
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
MemberIds []string `json:"memberIds" binding:"required"`
PersonId string `json:"-"`
}
type GroupRemoveResponse struct {
// 群人数
MemberNum int32 `json:"memberNum" form:"memberNum"`
// 成功被踢的成员列表
MemberIds []string `json:"memberIds"`
}
type GroupDisbandRequest struct {
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
}
type GroupDisbandResponse struct {
}
type UpdateGroupNameRequest struct {
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
Name string `json:"name"`
PublicName string `json:"publicName"`
}
type UpdateGroupNameResponse struct {
}
type UpdateGroupAvatarRequest struct {
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
Avatar string `json:"avatar"`
}
type UpdateGroupAvatarResponse struct {
}
type UpdateGroupMemberNameRequest struct {
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
MemberName string `json:"memberName"`
}
type UpdateGroupMemberNameResponse struct {
}
type UpdateGroupJoinTypeRequest struct {
// 群 ID
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
// 加群方式0=无需审批默认1=禁止加群,群主和管理员邀请加群, 2=普通人邀请需要审批,群主和管理员直接加群
JoinType int32 `json:"joinType" binding:"oneof=0 1 2"`
}
type UpdateGroupJoinTypeResponse struct {
}
type UpdateGroupFriendTypeRequest struct {
// 群 ID
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
// 加好友限制, 0=群内可加好友1=群内禁止加好友
FriendType int32 `json:"friendType" binding:"oneof=0 1"`
}
type UpdateGroupFriendTypeResponse struct {
}
type ChangeOwnerRequest struct {
// 群 ID
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
// 被转让为群主的群成员 ID
MemberId string `json:"memberId" binding:"required"`
PersonId string `json:"-"`
}
type ChangeOwnerResponse struct {
}
// JoinGroupReq 扫二维码加群
type JoinGroupReq struct {
Id int64 `json:"id"`
IdStr string `json:"idStr"`
InviterId string `json:"inviterId"`
PersonId string `json:"-"`
}
type JoinGroupResp struct {
Id int64 `json:"id"`
IdStr string `json:"idStr"`
}
type SetAdminRequest struct {
// 群 ID
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
// 被设置的群成员 ID
MemberId string `json:"memberId" binding:"required"`
PersonId string `json:"-"`
// 用户角色 0=群员, 1=管理员
MemberType int32 `json:"memberType" binding:"oneof=0 1"`
}
type SetAdminResponse struct {
}
type UpdateGroupMuteTypeRequest struct {
// 群 ID
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
// 禁言, 0=全员可发言, 1=全员禁言(除群主和管理员)
MuteType int32 `json:"muteType" binding:"oneof=0 1"`
PersonId string `json:"-"`
}
type UpdateGroupMuteTypeResponse struct {
}
type UpdateGroupMemberMuteTimeRequest struct {
// 群 ID
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
// 被禁言的群员 ID
MemberIds []string `json:"memberIds" binding:"required"`
// 禁言持续时间, 传9223372036854775807=永久禁言, 0=解除禁言
MuteTime int64 `json:"muteTime"`
PersonId string `json:"-"`
}
type UpdateGroupMemberMuteTimeResponse struct {
Members []*GroupMember `json:"members"`
}
type GetMuteListRequest struct {
// 群 ID
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
}
type GetMuteListResponse struct {
Members []*GroupMember `json:"members"`
}
type GetGroupPubInfoRequest struct {
// 群 ID
Id int64 `json:"id"`
// 如果同时填了 idStr, 则优先选择 idStr
IdStr string `json:"idStr"`
PersonId string `json:"-"`
}
type GetGroupPubInfoResponse struct {
*GroupInfo
}
type GetGroupInfoByConditionReq struct {
// 查询方法 0:groupMarkId, 1:groupId
Tp int32 `json:"tp" binding:"oneof=0 1"`
Query string `json:"query" binding:"required"`
PersonId string `json:"-"`
}
type GetGroupInfoByConditionResp struct {
Groups []*GroupInfo `json:"groups"`
}
// ---群审批------------------
// GroupApplyInfo 群审批信息
type GroupApplyInfo struct {
// 审批 ID
ApplyId string `json:"applyId,omitempty"`
// 群 ID
GroupId string `json:"id,omitempty"`
// 邀请人 ID, 空表示是自己主动申请的
InviterId string `json:"inviterId,omitempty"`
// 申请加入人 ID
MemberId string `json:"memberId,omitempty"`
// 申请备注
ApplyNote string `json:"applyNote,omitempty"`
// 审批人 ID
OperatorId string `json:"operatorId,omitempty"`
// 审批情况 0=待审批, 1=审批通过, 2=审批不通过, 10=审批忽略
ApplyStatus int32 `json:"applyStatus,omitempty"`
// 拒绝原因
RejectReason string `json:"rejectReason,omitempty"`
// 创建时间 ms
CreateTime int64 `json:"createTime,omitempty"`
// 修改时间 ms
UpdateTime int64 `json:"updateTime,omitempty"`
}
// CreateGroupApplyReq 创建群审批请求
type CreateGroupApplyReq struct {
// 群 ID
Id string `json:"id,omitempty" binding:"required"`
// 申请备注
ApplyNote string `json:"applyNote,omitempty"`
PersonId string `json:"-"`
}
// CreateGroupApplyResp 创建群审批响应
type CreateGroupApplyResp struct {
}
// GetGroupApplyByIdReq 查询群审批请求
type GetGroupApplyByIdReq struct {
// 审批 ID
ApplyId string `json:"applyId" binding:"required"`
// 群 ID
Id string `json:"id" binding:"required"`
PersonId string `json:"-"`
}
// GetGroupApplysReq 查询群审批列表请求
type GetGroupApplysReq struct {
// 群 ID
Id string `json:"id" binding:"required"`
// 每页记录数
Count int32 `json:"count" binding:"required"`
// 当前审批记录数量
Offset int32 `json:"offset"`
PersonId string `json:"-"`
}
// GetGroupApplysResp 查询群审批响应
type GetGroupApplysResp struct {
GroupApplys []*GroupApplyInfo `json:"applys"`
}
// AcceptGroupApplyReq 接受加群审批请求
type AcceptGroupApplyReq struct {
// 审批 ID
ApplyId string `json:"applyId" binding:"required"`
// 群 ID
Id string `json:"id" binding:"required"`
PersonId string `json:"-"`
}
type AcceptGroupApplyResp struct {
}
// RejectGroupApplyReq 拒绝加群审批请求
type RejectGroupApplyReq struct {
// 审批 ID
ApplyId string `json:"applyId" binding:"required"`
// 群 ID
Id string `json:"id" binding:"required"`
// 拒绝原因
RejectReason string `json:"rejectReason"`
PersonId string `json:"-"`
}
type RejectGroupApplyResp struct {
}

View File

@@ -0,0 +1,352 @@
package grpc
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/logic"
"time"
"gitlab.33.cn/chat/dtalk/pkg/interceptor/logger"
"gitlab.33.cn/chat/dtalk/pkg/interceptor/trace"
xgrpc "gitlab.33.cn/chat/dtalk/pkg/net/grpc"
pb "gitlab.33.cn/chat/dtalk/service/group/api"
"gitlab.33.cn/chat/dtalk/service/group/model"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/chat/dtalk/service/group/service"
"google.golang.org/grpc"
)
func New(cfg *xgrpc.ServerConfig, svr *service.Service) *xgrpc.Server {
connectionTimeout := grpc.ConnectionTimeout(time.Duration(cfg.Timeout))
logServerInterceptor := logger.NewServerInterceptor(svr.GetLog(), []string{
"/dtalk.group.Group/GetGroupIds",
"/dtalk.group.Group/CheckInGroup",
"/dtalk.group.Group/GetMemberIds",
"/dtalk.group.Group/CheckMute",
"/dtalk.group.Group/GetGroups",
"/dtalk.group.Group/GetMember",
"/dtalk.group.Group/GetGroupInfo",
})
var ws = xgrpc.NewServer(
cfg,
connectionTimeout,
grpc.ChainUnaryInterceptor(
xerror.ErrInterceptor,
trace.ServerUnaryInterceptor,
logServerInterceptor.Unary,
),
)
pb.RegisterGroupServer(ws.Server(), &server{svc: svr})
ws, err := ws.Start()
if err != nil {
panic(err)
}
return ws
}
type server struct {
pb.UnimplementedGroupServer
svc *service.Service
}
// GetGroupIds .
func (s *server) GetGroupIds(ctx context.Context, req *pb.GetGroupIdsRequest) (*pb.GetGroupIdsReply, error) {
memberId := req.MemberId
groupIds, err := s.svc.GetGroupIdsByMemberId(memberId)
if err != nil {
return nil, err
}
return &pb.GetGroupIdsReply{GroupIds: groupIds}, nil
}
// CheckInGroup .
func (s *server) CheckInGroup(ctx context.Context, req *pb.CheckInGroupRequest) (*pb.CheckInGroupReply, error) {
memberId := req.MemberId
groupId := req.GroupId
isOk, err := s.svc.CheckInGroup(memberId, groupId)
if err != nil {
return nil, err
}
return &pb.CheckInGroupReply{IsOk: isOk}, nil
}
// GetMemberIds 单独开一个得到 id 的
func (s *server) GetMemberIds(ctx context.Context, req *pb.GetMemberIdsRequest) (*pb.GetMemberIdsReply, error) {
groupId := req.GroupId
groupMembers, err := s.svc.GetMembersByGroupId(groupId)
if err != nil {
return nil, err
}
groupMemberIds := make([]string, len(groupMembers), len(groupMembers))
for i := range groupMembers {
groupMemberIds[i] = groupMembers[i].GroupMemberId
}
return &pb.GetMemberIdsReply{MemberIds: groupMemberIds}, nil
}
// CheckMute .
func (s *server) CheckMute(ctx context.Context, req *pb.CheckMuteRequest) (*pb.CheckMuteReply, error) {
groupId := req.GroupId
memberId := req.MemberId
muteTime, err := s.svc.GetGroupMemberMuteTime(groupId, memberId)
if err != nil {
return nil, err
}
nowTime := time.Now().UnixNano() / 1e6
res := &pb.CheckMuteReply{IsOk: false}
if muteTime > nowTime {
res.IsOk = true
}
return res, nil
}
// GetGroups 获得群列表
func (s *server) GetGroups(ctx context.Context, req *pb.GetGroupsReq) (*pb.GetGroupsResp, error) {
getGroupsReq := &types.GetGroupListRequest{
PersonId: req.Id,
}
getGroupsResp, err := s.svc.GetGroupListSvc(ctx, getGroupsReq)
if err != nil {
return nil, err
}
groupsInfo := make([]*pb.GroupInfo, len(getGroupsResp.Groups))
for i, group := range getGroupsResp.Groups {
groupsInfo[i] = &pb.GroupInfo{
Id: group.Id,
Name: group.Name,
Avatar: group.Avatar,
}
}
return &pb.GetGroupsResp{
Groups: groupsInfo,
}, nil
}
// GetMember .
func (s *server) GetMember(ctx context.Context, req *pb.GetMemberReq) (*pb.GetMemberResp, error) {
groupId := req.GroupId
memberId := req.MemberId
mem, err := s.svc.GetMemberByMemberIdAndGroupId(ctx, memberId, groupId)
if err != nil {
if err == model.ErrRecordNotExist {
return &pb.GetMemberResp{
GroupMemberType: biz.GroupMemberTypeOther,
}, nil
}
return nil, err
}
return &pb.GetMemberResp{
GroupId: mem.GroupId,
GroupMemberId: mem.GroupMemberId,
GroupMemberName: mem.GroupMemberName,
GroupMemberType: mem.GroupMemberType,
GroupMemberJoinTime: mem.GroupMemberJoinTime,
GroupMemberUpdateTime: 0,
}, nil
}
// ----------------- new ----------------
// GetGroupInfo 根据一个群 id 查询一个群信息
// oa 使用, 返回群信息和判断群是否被解散
func (s *server) GetGroupInfo(ctx context.Context, req *pb.GetGroupInfoReq) (*pb.GetGroupInfoResp, error) {
groupId := req.GroupId
group, err := s.svc.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
if err.Error() == xerror.NewError(xerror.GroupStatusDisBand).Error() {
return &pb.GetGroupInfoResp{
GroupId: groupId,
GroupExist: false,
GroupName: "",
GroupAvatar: "",
GroupOwnerId: "",
}, nil
} else {
return nil, err
}
}
return &pb.GetGroupInfoResp{
GroupId: group.GroupId,
GroupExist: true,
GroupName: group.GroupPubName,
GroupAvatar: group.GroupAvatar,
GroupOwnerId: group.GroupOwnerId,
}, nil
}
// ForceAddMember 增加群成员
// oa 专属
func (s *server) ForceAddMember(ctx context.Context, req *pb.ForceAddMemberReq) (*pb.ForceAddMemberResp, error) {
l := logic.NewForceAddMemberLogic(ctx, s.svc)
return l.ForceAddMember(req)
}
// ForceDeleteMember 删除群成员
// oa 专属, 退部门的时候退群
func (s *server) ForceDeleteMember(ctx context.Context, req *pb.ForceDeleteMemberReq) (*pb.ForceDeleteMemberResp, error) {
l := logic.NewForceDeleteMemberLogic(ctx, s.svc)
return l.ForceDeleteMember(req)
}
// ForceDisbandGroup .
func (s *server) ForceDisbandGroup(ctx context.Context, req *pb.ForceDisbandGroupReq) (*pb.ForceDisbandGroupResp, error) {
err := s.svc.GroupDisband(ctx, req.GroupId, req.OpeId)
if err != nil {
return nil, err
}
return &pb.ForceDisbandGroupResp{}, nil
}
// ForceUpdateGroupType .
func (s *server) ForceUpdateGroupType(ctx context.Context, req *pb.ForceUpdateGroupTypeReq) (*pb.ForceUpdateGroupTypeResp, error) {
err := s.svc.UpdateGroupType(req.GroupId, req.GroupType)
if err != nil {
return nil, err
}
return &pb.ForceUpdateGroupTypeResp{}, nil
}
// ForceAddMembers .
func (s *server) ForceAddMembers(ctx context.Context, req *pb.ForceAddMembersReq) (*pb.ForceAddMembersResp, error) {
l := logic.NewForceAddMembersLogic(ctx, s.svc)
return l.ForceAddMembers(req)
}
// ForceDeleteMembers .
func (s *server) ForceDeleteMembers(ctx context.Context, req *pb.ForceDeleteMembersReq) (*pb.ForceDeleteMembersResp, error) {
l := logic.NewForceDeleteMembersLogic(ctx, s.svc)
return l.ForceDeleteMembers(req)
}
// ForceJoinGroups .
func (s *server) ForceJoinGroups(ctx context.Context, req *pb.ForceJoinGroupsReq) (*pb.ForceJoinGroupsResp, error) {
l := logic.NewForceJoinGroupsLogic(ctx, s.svc)
return l.ForceJoinGroups(req)
}
// ForceExitGroups .
func (s *server) ForceExitGroups(ctx context.Context, req *pb.ForceExitGroupsReq) (*pb.ForceExitGroupsResp, error) {
l := logic.NewForceExitGroupsLogic(ctx, s.svc)
return l.ForceExitGroups(req)
}
// ForceChangeOwner .
func (s *server) ForceChangeOwner(ctx context.Context, req *pb.ForceChangeOwnerReq) (*pb.ForceChangeOwnerResp, error) {
l := logic.NewForceChangeOwnerLogic(ctx, s.svc)
return l.ForceChangeOwner(req)
}
// CreateGroup .
func (s *server) CreateGroup(ctx context.Context, req *pb.CreateGroupReq) (*pb.CreateGroupResp, error) {
l := logic.NewCreateGroupLogic(ctx, s.svc)
return l.CreateGroup(req)
}
// ChangeOwner .
func (s *server) ChangeOwner(ctx context.Context, req *pb.ChangeOwnerReq) (*pb.ChangeOwnerResp, error) {
l := logic.NewChangeOwnerLogic(ctx, s.svc)
return l.ChangeOwner(req)
}
func (s *server) GetGroupList(ctx context.Context, req *pb.GetGroupListReq) (*pb.GetGroupListResp, error) {
l := logic.NewGetGroupListLogic(ctx, s.svc)
return l.GetGroupList(req)
}
func (s *server) GetGroupMemberInfo(ctx context.Context, req *pb.GetGroupMemberInfoReq) (*pb.GetGroupMemberInfoResp, error) {
l := logic.NewGetGroupMemberInfoLogic(ctx, s.svc)
return l.GetGroupMemberInfo(req)
}
func (s *server) GetGroupMemberList(ctx context.Context, req *pb.GetGroupMemberListReq) (*pb.GetGroupMemberListResp, error) {
l := logic.NewGetGroupMemberListLogic(ctx, s.svc)
return l.GetGroupMemberList(req)
}
func (s *server) GetMuteList(ctx context.Context, req *pb.GetMuteListReq) (*pb.GetMuteListResp, error) {
l := logic.NewGetMuteListLogic(ctx, s.svc)
return l.GetMuteList(req)
}
func (s *server) GetPriGroupInfo(ctx context.Context, req *pb.GetPriGroupInfoReq) (*pb.GetPriGroupInfoResp, error) {
l := logic.NewGetPriGroupInfoLogic(ctx, s.svc)
return l.GetPriGroupInfo(req)
}
func (s *server) GetPubGroupInfo(ctx context.Context, req *pb.GetPubGroupInfoReq) (*pb.GetPubGroupInfoResp, error) {
l := logic.NewGetPubGroupInfoLogic(ctx, s.svc)
return l.GetPubGroupInfo(req)
}
func (s *server) GroupDisband(ctx context.Context, req *pb.GroupDisbandReq) (*pb.GroupDisbandResp, error) {
l := logic.NewGroupDisbandLogic(ctx, s.svc)
return l.GroupDisband(req)
}
func (s *server) GroupExit(ctx context.Context, req *pb.GroupExitReq) (*pb.GroupExitResp, error) {
l := logic.NewGroupExitLogic(ctx, s.svc)
return l.GroupExit(req)
}
func (s *server) GroupRemove(ctx context.Context, req *pb.GroupRemoveReq) (*pb.GroupRemoveResp, error) {
l := logic.NewGroupRemoveLogic(ctx, s.svc)
return l.GroupRemove(req)
}
func (s *server) InviteGroupMembers(ctx context.Context, req *pb.InviteGroupMembersReq) (*pb.InviteGroupMembersResp, error) {
l := logic.NewInviteGroupMembersLogic(ctx, s.svc)
return l.InviteGroupMembers(req)
}
func (s *server) SetAdmin(ctx context.Context, req *pb.SetAdminReq) (*pb.SetAdminResp, error) {
l := logic.NewSetAdminLogic(ctx, s.svc)
return l.SetAdmin(req)
}
func (s *server) UpdateGroupAvatar(ctx context.Context, req *pb.UpdateGroupAvatarReq) (*pb.UpdateGroupAvatarResp, error) {
l := logic.NewUpdateGroupAvatarLogic(ctx, s.svc)
return l.UpdateGroupAvatar(req)
}
func (s *server) UpdateGroupFriendType(ctx context.Context, req *pb.UpdateGroupFriendTypeReq) (*pb.UpdateGroupFriendTypeResp, error) {
l := logic.NewUpdateGroupFriendTypeLogic(ctx, s.svc)
return l.UpdateGroupFriendType(req)
}
func (s *server) UpdateGroupJoinType(ctx context.Context, req *pb.UpdateGroupJoinTypeReq) (*pb.UpdateGroupJoinTypeResp, error) {
l := logic.NewUpdateGroupJoinTypeLogic(ctx, s.svc)
return l.UpdateGroupJoinType(req)
}
func (s *server) UpdateGroupMemberMuteTime(ctx context.Context, req *pb.UpdateGroupMemberMuteTimeReq) (*pb.UpdateGroupMemberMuteTimeResp, error) {
l := logic.NewUpdateGroupMemberMuteTimeLogic(ctx, s.svc)
return l.UpdateGroupMemberMuteTime(req)
}
func (s *server) UpdateGroupMemberName(ctx context.Context, req *pb.UpdateGroupMemberNameReq) (*pb.UpdateGroupMemberNameResp, error) {
l := logic.NewUpdateGroupMemberNameLogic(ctx, s.svc)
return l.UpdateGroupMemberName(req)
}
func (s *server) UpdateGroupMuteType(ctx context.Context, req *pb.UpdateGroupMuteTypeReq) (*pb.UpdateGroupMuteTypeResp, error) {
l := logic.NewUpdateGroupMuteTypeLogic(ctx, s.svc)
return l.UpdateGroupMuteType(req)
}
func (s *server) UpdateGroupName(ctx context.Context, req *pb.UpdateGroupNameReq) (*pb.UpdateGroupNameResp, error) {
l := logic.NewUpdateGroupNameLogic(ctx, s.svc)
return l.UpdateGroupName(req)
}

View File

@@ -0,0 +1,974 @@
package http
import (
"github.com/gin-gonic/gin"
"gitlab.33.cn/chat/dtalk/pkg/api"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
logic "gitlab.33.cn/chat/dtalk/service/group/logic/http"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
// CreateGroup
// @Summary 创建群
// @Author chy@33.cn
// @Tags group 群动作
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.CreateGroupRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.CreateGroupResponse}
// @Router /app/create-group [post]
func CreateGroup(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.CreateGroupRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
req.Owner.MemberId = userId.(string)
req.Owner.MemberName = ""
req.Owner.MemberType = biz.GroupMemberTypeOwner
req.Members = make([]types.GroupMember, len(req.MemberIds), len(req.MemberIds))
for i, id := range req.MemberIds {
req.Members[i].MemberId = id
req.Members[i].MemberName = ""
req.Members[i].MemberType = biz.GroupMemberTypeNormal
}
res, err := svc.CreateGroupSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// InviteGroupMembers
// @Summary 邀请新群员
// @Author chy@33.cn
// @Tags group 群动作
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.InviteGroupMembersRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.InviteGroupMembersResponse}
// @Router /app/invite-group-members [post]
func InviteGroupMembers(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.InviteGroupMembersRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
req.Inviter.MemberId = userId.(string)
req.NewMembers = make([]types.GroupMember, len(req.NewMemberIds), len(req.NewMemberIds))
for i, id := range req.NewMemberIds {
req.NewMembers[i].MemberId = id
req.NewMembers[i].MemberName = ""
req.NewMembers[i].MemberType = biz.GroupMemberTypeNormal
}
res, err := svc.InviteGroupMembersSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// JoinGroup
// @Summary 直接进群
// @Author chy@33.cn
// @Tags group 群动作
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.JoinGroupReq false "body"
// @Success 200 {object} types.GeneralResponse{data=types.JoinGroupResp}
// @Router /app/join-group [post]
func JoinGroup(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.JoinGroupReq{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
req.PersonId = userId.(string)
// 走邀请函数
nreq := &types.InviteGroupMembersRequest{}
nreq.Id = req.Id
nreq.Inviter.MemberId = req.InviterId
nreq.NewMembers = make([]types.GroupMember, 1, 1)
nreq.NewMembers[0].MemberId = req.PersonId
nreq.NewMembers[0].MemberName = ""
nreq.NewMembers[0].MemberType = biz.GroupMemberTypeNormal
res, err := svc.InviteGroupMembersSvc(c, nreq)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GroupExit
// @Summary 退群
// @Author chy@33.cn
// @Tags group 群动作
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GroupExitRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GroupExitResponse}
// @Router /app/group-exit [post]
func GroupExit(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.GroupExitRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
req.PersonId = userId.(string)
res, err := svc.GroupExitHttp(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GroupRemove
// @Summary 踢人
// @Author chy@33.cn
// @Tags group 群动作
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GroupRemoveRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GroupRemoveResponse}
// @Router /app/group-remove [post]
func GroupRemove(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.GroupRemoveRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
req.PersonId = userId.(string)
res, err := svc.GroupRemoveSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GroupDisband
// @Summary 解散群
// @Author chy@33.cn
// @Tags group 群动作
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GroupDisbandRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GroupDisbandResponse}
// @Router /app/group-disband [post]
func GroupDisband(c *gin.Context) {
req := &types.GroupDisbandRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.GroupDisbandHttp(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// ChangeOwner
// @Summary 转让群
// @Author chy@33.cn
// @Tags group 群动作
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.ChangeOwnerRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.ChangeOwnerResponse}
// @Router /app/change-owner [post]
func ChangeOwner(c *gin.Context) {
req := &types.ChangeOwnerRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
l := logic.NewChangeOwnerLogic(c, svc)
res, err := l.ChangeOwner(req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupInfo
// @Summary 查询群信息
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GetGroupInfoRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupInfoResponse}
// @Router /app/group-info [post]
func GetGroupInfo(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.GetGroupInfoRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
req.PersonId = userId.(string)
if req.DisPlayNum == 0 {
req.DisPlayNum = biz.DisPlayNum
}
res, err := svc.GetGroupInfoHttp(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupPubInfo
// @Summary 查询群公开信息
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GetGroupPubInfoRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupPubInfoResponse}
// @Router /app/group-pub-info [post]
func GetGroupPubInfo(c *gin.Context) {
req := &types.GetGroupPubInfoRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.GetGroupPubInfoSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupList
// @Summary 查询群列表
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GetGroupListRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupListResponse}
// @Router /app/group-list [post]
func GetGroupList(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.GetGroupListRequest{}
req.PersonId = userId.(string)
res, err := svc.GetGroupListSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupMemberList
// @Summary 查询群成员列表
// @Author chy@33.cn
// @Tags group 群成员信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GetGroupMemberListRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupMemberListResponse}
// @Router /app/group-member-list [post]
func GetGroupMemberList(c *gin.Context) {
req := &types.GetGroupMemberListRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.GetGroupMemberListSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupMemberInfo
// @Summary 查询群成员信息
// @Author chy@33.cn
// @Tags group 群成员信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GetGroupMemberInfoRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupMemberInfoResponse}
// @Router /app/group-member-info [post]
func GetGroupMemberInfo(c *gin.Context) {
req := &types.GetGroupMemberInfoRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.GetGroupMemberInfoSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// UpdateGroupName
// @Summary 更新群名称
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.UpdateGroupNameRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.UpdateGroupNameResponse}
// @Router /app/name [post]
func UpdateGroupName(c *gin.Context) {
req := &types.UpdateGroupNameRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.UpdateGroupNameSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// UpdateGroupAvatar
// @Summary 更新群头像
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.UpdateGroupAvatarRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.UpdateGroupAvatarResponse}
// @Router /app/avatar [post]
func UpdateGroupAvatar(c *gin.Context) {
req := &types.UpdateGroupAvatarRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.UpdateGroupAvatarSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// UpdateGroupJoinType
// @Summary 更新加群设置
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.UpdateGroupJoinTypeRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.UpdateGroupJoinTypeResponse}
// @Router /app/joinType [post]
func UpdateGroupJoinType(c *gin.Context) {
req := &types.UpdateGroupJoinTypeRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.UpdateGroupJoinTypeSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// UpdateGroupFriendType
// @Summary 更新群内加好友设置
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.UpdateGroupFriendTypeRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.UpdateGroupFriendTypeResponse}
// @Router /app/friendType [post]
func UpdateGroupFriendType(c *gin.Context) {
req := &types.UpdateGroupFriendTypeRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.UpdateGroupFriendTypeSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// UpdateGroupMemberName
// @Summary 更新群成员昵称
// @Author chy@33.cn
// @Tags group 群成员信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.UpdateGroupMemberNameRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.UpdateGroupMemberNameResponse}
// @Router /app/member/name [post]
func UpdateGroupMemberName(c *gin.Context) {
req := &types.UpdateGroupMemberNameRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.UpdateMemberNameSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// SetAdmin
// @Summary 设置管理员
// @Author chy@33.cn
// @Tags group 群成员信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.SetAdminRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.SetAdminResponse}
// @Router /app/member/type [post]
func SetAdmin(c *gin.Context) {
req := &types.SetAdminRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.SetAdminSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// UpdateGroupMuteType
// @Summary 更新群禁言设置
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.UpdateGroupMuteTypeRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.UpdateGroupMuteTypeResponse}
// @Router /app/muteType [post]
func UpdateGroupMuteType(c *gin.Context) {
req := &types.UpdateGroupMuteTypeRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.UpdateGroupMuteTypeSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// SetMembersMuteTime
// @Summary 更新群成员禁言时间
// @Author chy@33.cn
// @Tags group 禁言
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.UpdateGroupMemberMuteTimeRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.UpdateGroupMemberMuteTimeResponse}
// @Router /app/member/muteTime [post]
func SetMembersMuteTime(c *gin.Context) {
req := &types.UpdateGroupMemberMuteTimeRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.UpdateMembersMuteTimeSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetMuteList
// @Summary 查询群内被禁言成员名单
// @Author chy@33.cn
// @Tags group 禁言
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GetMuteListRequest false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GetMuteListResponse}
// @Router /app/mute-list [post]
func GetMuteList(c *gin.Context) {
req := &types.GetMuteListRequest{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.GetMuteListSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupInfoById
// @Summary 查询群信息
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param id path integer true "群id"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupInfoResponse}
// @Router /app/group/{id} [get]
func GetGroupInfoById(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.GetGroupInfoRequest{}
err := c.ShouldBindUri(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
req.PersonId = userId.(string)
if req.DisPlayNum == 0 {
req.DisPlayNum = biz.DisPlayNum
}
res, err := svc.GetGroupInfoHttp(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroups
// @Summary 查询群列表
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupListResponse}
// @Router /app/groups [get]
func GetGroups(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.GetGroupListRequest{}
req.PersonId = userId.(string)
res, err := svc.GetGroupListSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupMemberInfoByUri
// @Summary 查询群成员信息
// @Author chy@33.cn
// @Tags group 群成员信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param id path integer true "群id"
// @Param memberId path integer true "群成员id"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupMemberInfoResponse}
// @Router /app/group/{id}/member/{memberId} [get]
func GetGroupMemberInfoByUri(c *gin.Context) {
req := &types.GetGroupMemberInfoRequest{}
err := c.ShouldBindUri(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.GetGroupMemberInfoSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupMemberListByUri
// @Summary 查询群成员列表
// @Author chy@33.cn
// @Tags group 群成员信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param id path integer true "群id"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupMemberListResponse}
// @Router /app/group/{id}/members [get]
func GetGroupMemberListByUri(c *gin.Context) {
req := &types.GetGroupMemberListRequest{}
err := c.ShouldBindUri(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
if req.Id == 0 && req.IdStr == "" {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError))
return
}
if req.IdStr != "" {
req.Id = convert.ToInt64(req.IdStr)
}
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req.PersonId = userId.(string)
res, err := svc.GetGroupMemberListSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupInfoByCondition
// @Summary 搜索群列表
// @Author chy@33.cn
// @Tags group 群信息
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GetGroupInfoByConditionReq false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupInfoByConditionResp}
// @Router /app/group-search [post]
func GetGroupInfoByCondition(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.GetGroupInfoByConditionReq{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
req.PersonId = userId.(string)
res, err := svc.GetGroupInfoByConditionSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}

View File

@@ -0,0 +1,152 @@
package http
import (
"github.com/gin-gonic/gin"
"gitlab.33.cn/chat/dtalk/pkg/api"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// CreateGroupApply
// @Summary 创建加群审批
// @Author chy@33.cn
// @Tags group 群审批
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.CreateGroupApplyReq false "body"
// @Success 200 {object} types.GeneralResponse{data=types.CreateGroupApplyResp}
// @Router /app/create-group-apply [post]
func CreateGroupApply(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.CreateGroupApplyReq{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
req.PersonId = userId.(string)
res, err := svc.CreateGroupApplySvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// AcceptGroupApply
// @Summary 接受加群审批
// @Author chy@33.cn
// @Tags group 群审批
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.AcceptGroupApplyReq false "body"
// @Success 200 {object} types.GeneralResponse{data=types.AcceptGroupApplyResp}
// @Router /app/accept-group-apply [post]
func AcceptGroupApply(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.AcceptGroupApplyReq{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
req.PersonId = userId.(string)
res, err := svc.AcceptGroupApplySvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// RejectGroupApply
// @Summary 拒绝加群审批
// @Author chy@33.cn
// @Tags group 群审批
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.RejectGroupApplyReq false "body"
// @Success 200 {object} types.GeneralResponse{data=types.RejectGroupApplyResp}
// @Router /app/reject-group-apply [post]
func RejectGroupApply(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.RejectGroupApplyReq{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
req.PersonId = userId.(string)
res, err := svc.RejectGroupApplySvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupApplyById
// @Summary 查询加群审批
// @Author chy@33.cn
// @Tags group 群审批
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GetGroupApplyByIdReq false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupApplysResp}
// @Router /app/get-group-apply [post]
func GetGroupApplyById(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.GetGroupApplyByIdReq{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
req.PersonId = userId.(string)
res, err := svc.GetGroupApplyByIdSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}
// GetGroupApplys
// @Summary 查询加群审批列表
// @Author chy@33.cn
// @Tags group 群审批
// @Param FZM-SIGNATURE header string true "MOCK"
// @Param data body types.GetGroupApplysReq false "body"
// @Success 200 {object} types.GeneralResponse{data=types.GetGroupApplysResp}
// @Router /app/get-group-applys [post]
func GetGroupApplys(c *gin.Context) {
userId, ok := c.Get(api.Address)
if !ok {
c.Set(api.ReqError, xerror.NewError(xerror.SignatureInvalid))
return
}
req := &types.GetGroupApplysReq{}
err := c.ShouldBind(req)
if err != nil {
c.Set(api.ReqError, xerror.NewError(xerror.ParamsError).SetExtMessage(err.Error()))
return
}
req.PersonId = userId.(string)
res, err := svc.GetGroupApplysSvc(c, req)
c.Set(api.ReqResult, res)
c.Set(api.ReqError, err)
}

View File

@@ -0,0 +1,110 @@
package http
import (
"net/http"
"gitlab.33.cn/chat/dtalk/pkg/api/logger"
"gitlab.33.cn/chat/dtalk/pkg/api/trace"
"github.com/gin-gonic/gin"
"github.com/inconshreveable/log15"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"gitlab.33.cn/chat/dtalk/pkg/api"
_ "gitlab.33.cn/chat/dtalk/service/group/docs"
"gitlab.33.cn/chat/dtalk/service/group/service"
)
var (
svc *service.Service
log = log15.New("module", "group/http")
)
func Init(s *service.Service) *http.Server {
addr := s.Config().HttpServer.Addr
if s.Config().Env != "debug" {
gin.SetMode(gin.ReleaseMode)
}
engine := Default()
InitService(s)
SetupEngine(engine)
srv := &http.Server{
Addr: addr,
Handler: engine,
}
go func() {
// service connections
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Error("", "engineInner.Start() error(%v)", err)
panic(err)
}
}()
return srv
}
// Default returns an Engine instance with the Logger and Recovery middleware already attached.
func Default() *gin.Engine {
router := gin.New()
// LoggerWithFormatter middleware will write the logs to gin.DefaultWriter
// By default gin.DefaultWriter = os.Stdout
//router.Use(gin.LoggerWithFormatter(api.Chat33GinLogFormatter))
router.Use(gin.Recovery())
return router
}
func InitService(s *service.Service) {
svc = s
}
// SetupEngine
// @title 群服务接口
// @version 1.0
// @host 127.0.0.1:18011
func SetupEngine(e *gin.Engine) *gin.Engine {
group := e.Group("/app", api.RespMiddleWare())
logMiddleware := logger.NewMiddleware(svc.GetLog())
group.Use(api.AuthMiddleWare(), trace.TraceMiddleware(), logMiddleware.Handle())
{
group.POST("/create-group", CreateGroup)
group.POST("/invite-group-members", InviteGroupMembers)
group.POST("/group-exit", GroupExit)
group.POST("/group-disband", GroupDisband)
group.POST("/group-remove", GroupRemove)
group.POST("/change-owner", ChangeOwner)
group.POST("/join-group", JoinGroup)
group.POST("/name", UpdateGroupName)
group.POST("/avatar", UpdateGroupAvatar)
group.POST("/joinType", UpdateGroupJoinType)
group.POST("/friendType", UpdateGroupFriendType)
group.POST("/muteType", UpdateGroupMuteType)
group.POST("/member/name", UpdateGroupMemberName)
group.POST("/member/type", SetAdmin)
group.POST("/member/muteTime", SetMembersMuteTime)
//group.GET("/group/:id", GetGroupInfoById)
group.POST("/group-info", GetGroupInfo)
group.POST("/group-pub-info", GetGroupPubInfo)
//group.GET("/groups", GetGroups)
group.POST("/group-list", GetGroupList)
group.POST("/group-search", GetGroupInfoByCondition)
//group.GET("/group/:id/members", GetGroupMemberListByUri)
group.POST("/group-member-list", GetGroupMemberList)
//group.GET("/group/:id/member/:memberId", GetGroupMemberInfoByUri)
group.POST("/group-member-info", GetGroupMemberInfo)
group.POST("/mute-list", GetMuteList)
group.POST("/create-group-apply", CreateGroupApply)
group.POST("/accept-group-apply", AcceptGroupApply)
group.POST("/reject-group-apply", RejectGroupApply)
group.POST("/get-group-apply", GetGroupApplyById)
group.POST("/get-group-applys", GetGroupApplys)
}
// prometheus 接口
//e.GET("/prometheus", midware.PrometheusHandler())
// swagger 文档接口
e.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
return e
}

View File

@@ -0,0 +1,96 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
// AcceptGroupApplySvc 接受 申请加入团队 的审批
func (s *Service) AcceptGroupApplySvc(ctx context.Context, req *types.AcceptGroupApplyReq) (res *types.AcceptGroupApplyResp, err error) {
//log := s.GetLogWithTrace(ctx)
personId := req.PersonId
groupId := convert.ToInt64(req.Id)
applyId := convert.ToInt64(req.ApplyId)
// 查询审批详情
groupApply, err := s.getGroupApplyById(applyId)
if err != nil {
return nil, err
}
// 判断审批是否被处理过
if err = groupApply.IsWait(); err != nil {
return nil, err
}
// 查询操作人详情并判断是否有权限操作
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
// 查询群详情
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
// 判断群人数上限
if err = group.TryJoin(1); err != nil {
return nil, err
}
// 处理审批
groupApply.ApplyStatus = biz.GroupApplyAccept
groupApply.OperatorId = personId
err = s.updateGroupApply(groupApply)
if err != nil {
return nil, err
}
// 判断是否已经在群内
if isExit, err := s.CheckInGroup(groupApply.MemberId, groupId); err != nil {
return nil, err
} else if isExit == true {
err = xerror.NewError(xerror.GroupInviteMemberExist)
return nil, err
}
// 加人
nowTime := s.getNowTime()
newMember := &db.GroupMember{
GroupId: groupId,
GroupMemberId: groupApply.MemberId,
GroupMemberName: "",
GroupMemberType: 0,
GroupMemberJoinTime: nowTime,
GroupMemberUpdateTime: nowTime,
}
opeId := groupApply.InviterId
if opeId == "" {
opeId = groupApply.OperatorId
}
if err = s.AddGroupMembers(ctx, group.GroupId, []*db.GroupMember{newMember}, opeId); err != nil {
return nil, err
}
return &types.AcceptGroupApplyResp{}, nil
}
func (s *Service) updateGroupApply(biz *biz.GroupApplyBiz) error {
err := s.dao.UpdateGroupApply(biz.OperatorId, biz.ApplyStatus, biz.RejectReason, biz.ApplyId)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,240 @@
package service
import (
"context"
"gitlab.33.cn/utils/go-kit/convert"
"github.com/golang/protobuf/proto"
"github.com/google/uuid"
"gitlab.33.cn/chat/dtalk/service/group/model"
answer "gitlab.33.cn/chat/dtalk/service/record/answer/api"
xproto "gitlab.33.cn/chat/imparse/proto"
)
func (s *Service) PushNoticeMsg(ctx context.Context, channelType int32, from, target string, data []byte) error {
noticeMsgReq := &answer.PushNoticeMsgReq{
Seq: uuid.New().String(),
ChannelType: channelType,
From: from,
Target: target,
Data: data,
}
if _, err := s.answerClient.PushNoticeMsg(
ctx, noticeMsgReq.Seq, noticeMsgReq.ChannelType,
noticeMsgReq.From, noticeMsgReq.Target, noticeMsgReq.Data); err != nil {
return err
}
return nil
}
func (s *Service) PushGroupNoticeMsg(ctx context.Context, groupId int64, personId string, noticeMsgMsg *xproto.NoticeMsg) error {
data, err := proto.Marshal(noticeMsgMsg)
if err != nil {
return err
}
from := personId
target := convert.ToString(groupId)
if err = s.PushNoticeMsg(ctx, 1, from, target, data); err != nil {
return err
}
return nil
}
func convertNoticeMsgMsg(noticeMsgType xproto.NoticeMsgType, noticeMsg proto.Message) (*xproto.NoticeMsg, error) {
body, err := proto.Marshal(noticeMsg)
if err != nil {
return nil, err
}
noticeMsgMsg := &xproto.NoticeMsg{
Type: noticeMsgType,
Body: body,
}
return noticeMsgMsg, nil
}
func (s *Service) NoticeMsgUpdateGroupName(ctx context.Context, groupId int64, personId string, name string) error {
if name == "" {
return nil
}
noticeMsgType := xproto.NoticeMsgType_UpdateGroupNameNoticeMsg
noticeMsg := &xproto.NoticeMsgUpdateGroupName{
Group: groupId,
Operator: personId,
Name: name,
}
noticeMsgMsg, err := convertNoticeMsgMsg(noticeMsgType, noticeMsg)
if err != nil {
return err
}
if err = s.PushGroupNoticeMsg(ctx, groupId, personId, noticeMsgMsg); err != nil {
return err
}
return nil
}
func (s *Service) NoticeMsgSignInGroup(ctx context.Context, groupId int64, personId string, memberIds []string) error {
noticeMsgType := xproto.NoticeMsgType_SignInGroupNoticeMsg
noticeMsg := &xproto.NoticeMsgSignInGroup{
Group: groupId,
Inviter: personId,
Members: memberIds,
}
noticeMsgMsg, err := convertNoticeMsgMsg(noticeMsgType, noticeMsg)
if err != nil {
return err
}
if err = s.PushGroupNoticeMsg(ctx, groupId, personId, noticeMsgMsg); err != nil {
return err
}
return nil
}
func (s *Service) NoticeMsgSignOutGroup(ctx context.Context, groupId int64, personId string) error {
noticeMsgType := xproto.NoticeMsgType_SignOutGroupNoticeMsg
noticeMsg := &xproto.NoticeMsgSignOutGroup{
Group: groupId,
Operator: personId,
}
body, err := proto.Marshal(noticeMsg)
if err != nil {
return err
}
noticeMsgMsg := &xproto.NoticeMsg{
Type: noticeMsgType,
Body: body,
}
if err = s.PushGroupNoticeMsg(ctx, groupId, personId, noticeMsgMsg); err != nil {
return err
}
return nil
}
func (s *Service) NoticeMsgKickOutGroup(ctx context.Context, groupId int64, personId string, memberIds []string) error {
noticeMsgType := xproto.NoticeMsgType_KickOutGroupNoticeMsg
noticeMsg := &xproto.NoticeMsgKickOutGroup{
Group: groupId,
Operator: personId,
Members: memberIds,
}
body, err := proto.Marshal(noticeMsg)
if err != nil {
return err
}
noticeMsgMsg := &xproto.NoticeMsg{
Type: noticeMsgType,
Body: body,
}
if err = s.PushGroupNoticeMsg(ctx, groupId, personId, noticeMsgMsg); err != nil {
return err
}
return nil
}
func (s *Service) NoticeMsgDeleteGroup(ctx context.Context, groupId int64, personId string) error {
noticeMsgType := xproto.NoticeMsgType_DeleteGroupNoticeMsg
noticeMsg := &xproto.NoticeMsgDeleteGroup{
Group: groupId,
Operator: personId,
}
body, err := proto.Marshal(noticeMsg)
if err != nil {
return err
}
noticeMsgMsg := &xproto.NoticeMsg{
Type: noticeMsgType,
Body: body,
}
if err = s.PushGroupNoticeMsg(ctx, groupId, personId, noticeMsgMsg); err != nil {
return err
}
return nil
}
func (s *Service) NoticeMsgUpdateGroupMuted(ctx context.Context, groupId int64, personId string, muteType int32) error {
var proMuteType xproto.MuteType
switch muteType {
case int32(xproto.MuteType_MuteAllow):
proMuteType = xproto.MuteType_MuteAllow
case int32(xproto.MuteType_MuteDeny):
proMuteType = xproto.MuteType_MuteDeny
default:
return model.ErrType
}
noticeMsgType := xproto.NoticeMsgType_UpdateGroupMutedNoticeMsg
noticeMsg := &xproto.NoticeMsgUpdateGroupMuted{
Group: groupId,
Operator: personId,
Type: proMuteType,
}
body, err := proto.Marshal(noticeMsg)
if err != nil {
return err
}
noticeMsgMsg := &xproto.NoticeMsg{
Type: noticeMsgType,
Body: body,
}
if err = s.PushGroupNoticeMsg(ctx, groupId, personId, noticeMsgMsg); err != nil {
return err
}
return nil
}
func (s *Service) NoticeMsgUpdateGroupMemberMutedTime(ctx context.Context, groupId int64, personId string, memberIds []string) error {
noticeMsgType := xproto.NoticeMsgType_UpdateGroupMemberMutedNoticeMsg
noticeMsg := &xproto.NoticeMsgUpdateGroupMemberMutedTime{
Group: groupId,
Operator: personId,
Members: memberIds,
}
body, err := proto.Marshal(noticeMsg)
if err != nil {
return err
}
noticeMsgMsg := &xproto.NoticeMsg{
Type: noticeMsgType,
Body: body,
}
if err = s.PushGroupNoticeMsg(ctx, groupId, personId, noticeMsgMsg); err != nil {
return err
}
return nil
}
func (s *Service) NoticeMsgUpdateGroupOwner(ctx context.Context, groupId int64, personId, newOwner string) error {
noticeMsgType := xproto.NoticeMsgType_UpdateGroupOwnerNoticeMsg
noticeMsg := &xproto.NoticeMsgUpdateGroupOwner{
Group: groupId,
NewOwner: newOwner,
}
body, err := proto.Marshal(noticeMsg)
if err != nil {
return err
}
noticeMsgMsg := &xproto.NoticeMsg{
Type: noticeMsgType,
Body: body,
}
if err = s.PushGroupNoticeMsg(ctx, groupId, personId, noticeMsgMsg); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,288 @@
package service
import (
"context"
"github.com/golang/protobuf/proto"
"gitlab.33.cn/chat/dtalk/service/group/model"
xproto "gitlab.33.cn/chat/imparse/proto"
"gitlab.33.cn/utils/go-kit/convert"
)
func (s *Service) PusherSignalJoin(ctx context.Context, groupId int64, groupMemberIds []string) error {
nowTime := s.getNowTime()
actionSignInGroup := &xproto.SignalSignInGroup{
Uid: groupMemberIds,
Group: groupId,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(actionSignInGroup)
if err != nil {
return err
}
Signal := xproto.SignalType_SignInGroup
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}
func (s *Service) PusherSignalLeave(ctx context.Context, groupId int64, groupMemberIds []string) error {
nowTime := s.getNowTime()
actionSignOutGroup := &xproto.SignalSignOutGroup{
Uid: groupMemberIds,
Group: groupId,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(actionSignOutGroup)
if err != nil {
return err
}
Signal := xproto.SignalType_SignOutGroup
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}
func (s *Service) PusherSignalDel(ctx context.Context, groupId int64) error {
nowTime := s.getNowTime()
actionDealeteGroup := &xproto.SignalDeleteGroup{
Group: groupId,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(actionDealeteGroup)
if err != nil {
return err
}
Signal := xproto.SignalType_DeleteGroup
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}
func (s *Service) PusherSignalJoinType(ctx context.Context, groupId int64, joinType int32) error {
nowTime := s.getNowTime()
var proJoinType xproto.JoinType
switch joinType {
case int32(xproto.JoinType_JoinAllow):
proJoinType = xproto.JoinType_JoinAllow
case int32(xproto.JoinType_JoinDeny):
proJoinType = xproto.JoinType_JoinDeny
case int32(xproto.JoinType_JoinApply):
proJoinType = xproto.JoinType_JoinApply
default:
return model.ErrType
}
action := &xproto.SignalUpdateGroupJoinType{
Group: groupId,
Type: proJoinType,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(action)
if err != nil {
return err
}
Signal := xproto.SignalType_UpdateGroupJoinType
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}
func (s *Service) PusherSignalFriendType(ctx context.Context, groupId int64, friendType int32) error {
nowTime := s.getNowTime()
var proFriendType xproto.FriendType
switch friendType {
case int32(xproto.FriendType_FriendAllow):
proFriendType = xproto.FriendType_FriendAllow
case int32(xproto.FriendType_FriendDeny):
proFriendType = xproto.FriendType_FriendDeny
default:
return model.ErrType
}
action := &xproto.SignalUpdateGroupFriendType{
Group: groupId,
Type: proFriendType,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(action)
if err != nil {
return err
}
Signal := xproto.SignalType_UpdateGroupFriendType
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}
func (s *Service) PusherSignalMuteType(ctx context.Context, groupId int64, muteType int32) error {
nowTime := s.getNowTime()
var proMuteType xproto.MuteType
switch muteType {
case int32(xproto.MuteType_MuteAllow):
proMuteType = xproto.MuteType_MuteAllow
case int32(xproto.MuteType_MuteDeny):
proMuteType = xproto.MuteType_MuteDeny
default:
return model.ErrType
}
action := &xproto.SignalUpdateGroupMuteType{
Group: groupId,
Type: proMuteType,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(action)
if err != nil {
return err
}
Signal := xproto.SignalType_UpdateGroupMuteType
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}
func (s *Service) PusherSignalMemberType(ctx context.Context, groupId int64, memberId string, memberType int32) error {
nowTime := s.getNowTime()
var proMemberType xproto.MemberType
switch memberType {
case int32(xproto.MemberType_Normal):
proMemberType = xproto.MemberType_Normal
case int32(xproto.MemberType_Admin):
proMemberType = xproto.MemberType_Admin
case int32(xproto.MemberType_Owner):
proMemberType = xproto.MemberType_Owner
default:
return model.ErrType
}
action := &xproto.SignalUpdateGroupMemberType{
Group: groupId,
Type: proMemberType,
Uid: memberId,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(action)
if err != nil {
return err
}
Signal := xproto.SignalType_UpdateGroupMemberType
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}
func (s *Service) PusherSignalMemberMuteTime(ctx context.Context, groupId int64, memberIds []string, muteTime int64) error {
nowTime := s.getNowTime()
action := &xproto.SignalUpdateGroupMemberMuteTime{
Group: groupId,
Uid: memberIds,
MuteTime: muteTime,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(action)
if err != nil {
return err
}
Signal := xproto.SignalType_UpdateGroupMemberMuteTime
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}
func (s *Service) PusherSignalGroupName(ctx context.Context, groupId int64, name string) error {
if name == "" {
return nil
}
nowTime := s.getNowTime()
action := &xproto.SignalUpdateGroupName{
Group: groupId,
Name: name,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(action)
if err != nil {
return err
}
Signal := xproto.SignalType_UpdateGroupName
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}
func (s *Service) PusherSignalGroupAvatar(ctx context.Context, groupId int64, avatar string) error {
nowTime := s.getNowTime()
action := &xproto.SignalUpdateGroupAvatar{
Group: groupId,
Avatar: avatar,
Time: convert.ToUint64(nowTime),
}
body, err := proto.Marshal(action)
if err != nil {
return err
}
Signal := xproto.SignalType_UpdateGroupAvatar
Target := convert.ToString(groupId)
Body := body
if err = s.answerClient.GroupCastSignal(ctx, Signal, Target, Body); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,35 @@
package service
// 组合各种数据访问来构建业务逻辑。
import (
"gitlab.33.cn/chat/dtalk/pkg/mysql"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"time"
)
func (s *Service) getNowTime() int64 {
return time.Now().UnixNano() / 1e6
}
// CheckInGroup 查询并检查该成员是否在群中
func (s *Service) CheckInGroup(memberId string, groupId int64) (bool, error) {
memberType, err := s.dao.GetMemberTypeMemberIdAndGroupId(memberId, groupId)
if err != nil {
return false, err
}
if memberType == biz.GroupMemberTypeOther {
return false, nil
}
return true, nil
}
// InsertGroupMembers 批量插入群成员
func (s *Service) InsertGroupMembers(tx *mysql.MysqlTx, groupMembers []*db.GroupMember) error {
err := s.dao.InsertGroupMembers(tx, groupMembers)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,93 @@
package service
import (
"context"
"errors"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
)
// GetGroupInfoByGroupId 根据 GroupId 查询群信息
func (s *Service) GetGroupInfoByGroupId(ctx context.Context, groupId int64) (*biz.GroupInfo, error) {
groupInfo, err := s.dao.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
if errors.Is(err, model.ErrRecordNotExist) {
return nil, xerror.NewError(xerror.GroupNotExist)
}
return nil, err
}
if err = groupInfo.IsNormal(); err != nil {
return nil, err
}
return groupInfo, nil
}
// GetGroupInfoByGroupMarkId 根据 GroupMarkId 查询群信息
// 没用到
func (s *Service) GetGroupInfoByGroupMarkId(groupMarkId string) (*biz.GroupInfo, error) {
groupInfo, err := s.dao.GetGroupInfoByGroupMarkId(groupMarkId)
if err != nil {
if errors.Is(err, model.ErrRecordNotExist) {
return nil, xerror.NewError(xerror.GroupNotExist)
}
return nil, err
}
return groupInfo, nil
}
// UpdateGroupInfoMemberNum 更新群成员数量
func (s *Service) UpdateGroupInfoMemberNum(ctx context.Context, groupId int64) (int32, error) {
n, err := s.dao.UpdateGroupInfoMemberNum(ctx, groupId)
if err != nil {
return 0, err
}
return n, nil
}
// GetGroupIdsByMemberId 查询用户所有加入的群 ID
func (s *Service) GetGroupIdsByMemberId(memberId string) ([]int64, error) {
groupIds, err := s.dao.GetGroupIdsByMemberId(memberId)
if err != nil {
return nil, err
}
return groupIds, nil
}
// GetGroupsByGroupIds 查询用户所有加入的群
// todo: 有 bug
func (s *Service) GetGroupsByGroupIds(ctx context.Context, groupIds []int64) ([]*biz.GroupInfo, error) {
groups, err := s.dao.GetGroupInfosByGroupIds(ctx, groupIds)
if err != nil {
return nil, err
}
return groups, nil
}
// CheckGroupMemberNum 检查新增群员是否会超过群人数上限
func (s *Service) CheckGroupMemberNum(newMembers int32, groupMaximum int32) error {
if newMembers > groupMaximum {
return xerror.NewError(xerror.GroupMemberLimit)
}
return nil
}
// UpdateGroupType 更新群类型
// rpc 专用
func (s *Service) UpdateGroupType(groupId int64, groupType int32) error {
// todo check groupType
_, _, err := s.dao.MaintainGroupType(&db.GroupInfo{
GroupId: groupId,
GroupType: groupType,
})
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,90 @@
package service
import (
"context"
"github.com/pkg/errors"
"gitlab.33.cn/chat/dtalk/pkg/contextx"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
)
// GetMemberByMemberIdAndGroupId 查询对方在群里的信息
func (s *Service) GetMemberByMemberIdAndGroupId(ctx context.Context, memberId string, groupId int64) (*biz.GroupMember, error) {
member, err := s.dao.GetGroupMemberByGroupIdAndMemberId(ctx, groupId, memberId)
if err != nil {
if errors.Is(err, model.ErrRecordNotExist) {
return nil, xerror.NewError(xerror.GroupMemberNotExist)
}
return nil, err
}
return member, nil
}
// GetPersonByMemberIdAndGroupId 查询本人在群里的信息
func (s *Service) GetPersonByMemberIdAndGroupId(ctx context.Context, memberId string, groupId int64) (*biz.GroupMember, error) {
member, err := s.dao.GetGroupMemberByGroupIdAndMemberId(ctx, groupId, memberId)
if err != nil {
if errors.Is(err, model.ErrRecordNotExist) {
return nil, xerror.NewError(xerror.GroupPersonNotExist)
}
return nil, err
}
return member, nil
}
// GetGroupMembersByGroupIdWithLimit 查询群内前 n 个群成员信息
func (s *Service) GetGroupMembersByGroupIdWithLimit(groupId, n, m int64) ([]*biz.GroupMember, error) {
members, err := s.dao.GetGroupMembersByGroupIdWithLimit(groupId, n, m)
if err != nil {
return nil, err
}
return members, nil
}
// GetMembersByGroupId 查询群里的所有成员信息
func (s *Service) GetMembersByGroupId(groupId int64) ([]*biz.GroupMember, error) {
res, err := s.dao.GetMembersByGroupId(groupId)
if err != nil {
return nil, err
}
return res, nil
}
// GetGroupMemberMuteTime 查询群成员禁言时间
func (s *Service) GetGroupMemberMuteTime(groupId int64, memberId string) (int64, error) {
muteTime, err := s.dao.GetGroupMemberMuteTime(groupId, memberId)
if err != nil {
return 0, err
}
return muteTime, nil
}
// AddGroupMembers 加群并发送通知
func (s *Service) AddGroupMembers(ctx context.Context, groupId int64, members []*db.GroupMember, opeId string) error {
log := s.GetLogWithTrace(ctx)
if err := s.ExecJoinGroupMembers(members); err != nil {
return err
}
// 更新群人数
_, err := s.UpdateGroupInfoMemberNum(ctx, groupId)
if err != nil {
// todo
log.Error().Err(err).Msg("AddGroupMembers")
}
memberIds := make([]string, 0, len(members))
for _, member := range members {
memberIds = append(memberIds, member.GroupMemberId)
}
go s.NoticeInviteMembers(contextx.ValueOnlyFrom(ctx), groupId, opeId, memberIds)
return nil
}

View File

@@ -0,0 +1,83 @@
package service
import (
"context"
"fmt"
"gitlab.33.cn/utils/go-kit/convert"
"time"
"github.com/pkg/errors"
"gitlab.33.cn/chat/dtalk/service/group/model"
logic "gitlab.33.cn/chat/im/api/logic/grpc"
)
func (s *Service) LogicNoticeJoin(ctx context.Context, groupId int64, groupMemberIds []string) error {
gid := make([]string, 1, 1)
gid[0] = convert.ToString(groupId)
groupMid := &logic.GroupsMid{
AppId: s.cfg.AppId,
Gid: gid,
Mids: groupMemberIds,
}
reply, err := s.logicClient.JoinGroupsByMids(ctx, groupMid)
if err != nil {
if err.Error() == model.ErrPushMsgArg.Error() {
return nil
}
return err
} else if reply.IsOk == false {
return errors.New(fmt.Sprintf("reply=%+v", reply))
}
return nil
}
func (s *Service) LogicNoticeLeave(ctx context.Context, groupId int64, groupMemberIds []string) error {
// 保证离开前的通知收到
time.Sleep(3 * time.Second)
gid := make([]string, 1, 1)
gid[0] = convert.ToString(groupId)
groupMid := &logic.GroupsMid{
AppId: s.cfg.AppId,
Gid: gid,
Mids: groupMemberIds,
}
reply, err := s.logicClient.LeaveGroupsByMids(ctx, groupMid)
if err != nil {
if err.Error() == model.ErrPushMsgArg.Error() {
return nil
}
return err
} else if reply.IsOk == false {
return errors.New(fmt.Sprintf("reply=%+v", reply))
}
return nil
}
func (s *Service) LogicNoticeDel(ctx context.Context, groupId int64) error {
// 保证离开前的通知收到
time.Sleep(3 * time.Second)
gid := make([]string, 1, 1)
gid[0] = convert.ToString(groupId)
delGroupsReq := &logic.DelGroupsReq{
AppId: s.cfg.AppId,
Gid: gid,
}
reply, err := s.logicClient.DelGroups(ctx, delGroupsReq)
if err != nil {
return err
} else if reply.IsOk == false {
return errors.New(fmt.Sprintf("reply=%+v", reply))
}
return nil
}

View File

@@ -0,0 +1,24 @@
package service
import "context"
// NoticeInviteMembers 新成员加入群发起通知
func (s *Service) NoticeInviteMembers(ctx context.Context, groupId int64, inviterId string, newMembers []string) {
log := s.GetLogWithTrace(ctx)
// 通知 logic
if err := s.LogicNoticeJoin(ctx, groupId, newMembers); err != nil {
log.Error().Err(err).Msg("inviteMemberNotice logic")
}
// 发送给 pusher
if err := s.PusherSignalJoin(ctx, groupId, newMembers); err != nil {
log.Error().Err(err).Msg("inviteMemberNotice pusher")
}
if err := s.NoticeMsgSignInGroup(ctx, groupId, inviterId, newMembers); err != nil {
log.Error().Err(err).Msg("inviteMemberNotice alert")
}
}
//

View File

@@ -0,0 +1,108 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/pkg/contextx"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
)
func (s *Service) ChangeOwner(ctx context.Context, group *biz.GroupInfo, owner, member *biz.GroupMember) error {
groupId := group.GroupId
ownerId := owner.GroupMemberId
memberId := member.GroupMemberId
var err error
log := s.GetLogWithTrace(ctx)
if err = s.ExecChangeOwner(groupId, ownerId, memberId); err != nil {
return err
}
go func() {
// 发送给 pusher
if err = s.PusherSignalMemberType(contextx.ValueOnlyFrom(ctx), groupId, memberId, biz.GroupMemberTypeOwner); err != nil {
log.Error().Err(err).Msg("ChangeOwnerHttp pusher")
}
// 发送给 pusher
if err = s.PusherSignalMemberType(contextx.ValueOnlyFrom(ctx), groupId, ownerId, biz.GroupMemberTypeNormal); err != nil {
log.Error().Err(err).Msg("ChangeOwnerHttp pusher")
}
// 发送给 alert
if err = s.NoticeMsgUpdateGroupOwner(contextx.ValueOnlyFrom(ctx), groupId, ownerId, memberId); err != nil {
log.Error().Err(err).Msg("ChangeOwnerHttp alert")
}
}()
// 解除新群主禁言
nowTime := s.getNowTime()
groupMemberMute := make([]*db.GroupMemberMute, 1, 1)
groupMemberMute[0] = &db.GroupMemberMute{
GroupId: groupId,
GroupMemberId: memberId,
GroupMemberMuteTime: 0,
GroupMemberMuteUpdateTime: nowTime,
}
if err = s.execSetMemberMuteTimes(ctx, groupMemberMute); err != nil {
return err
}
// 发送给 pusher
if err = s.PusherSignalMemberMuteTime(contextx.ValueOnlyFrom(ctx), groupId, []string{memberId}, 0); err != nil {
log.Error().Err(err).Msg("UpdateMembersMuteTimeSvc pusher")
}
return nil
}
// ExecChangeOwner 转让群主
func (s *Service) ExecChangeOwner(groupId int64, ownerId, memberId string) error {
// todo
// 如果并发换群主可能出现两个群主的情况
nowTime := s.getNowTime()
tx, err := s.dao.NewTx()
if err != nil {
return err
}
defer tx.RollBack()
groupInfo := &db.GroupInfo{
GroupId: groupId,
GroupOwnerId: memberId,
GroupUpdateTime: nowTime,
}
if _, _, err = s.dao.UpdateGroupInfoOwnerIdWithTx(tx, groupInfo); err != nil {
return err
}
owner := &db.GroupMember{
GroupId: groupId,
GroupMemberId: ownerId,
GroupMemberType: biz.GroupMemberTypeNormal,
GroupMemberUpdateTime: nowTime,
}
if _, _, err := s.dao.UpdateGroupMemberTypeWithTx(tx, owner); err != nil {
return err
}
member := &db.GroupMember{
GroupId: groupId,
GroupMemberId: memberId,
GroupMemberType: biz.GroupMemberTypeOwner,
GroupMemberUpdateTime: nowTime,
}
if _, _, err = s.dao.UpdateGroupMemberTypeWithTx(tx, member); err != nil {
return err
}
if err = tx.Commit(); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,76 @@
package service
//type SvcCtxOpt func(ctx context.Context) (context.Context, error)
//// SetContext 设置业务 ctx, opt 需要按照顺序填写
//func (s *Service) SetContext(ctx context.Context, options ...SvcCtxOpt) (context.Context, error) {
// var err error
// for _, opt := range options {
// ctx, err = opt(ctx)
// if err != nil {
// return nil, err
// }
// }
// return ctx, nil
//}
//
//func (s *Service) WithGroupInfoCtxOpt(ctx context.Context) (context.Context, error) {
// groupId, err := biz.NewGroupIdFromContext(ctx)
// if err != nil {
// return nil, err
// }
//
// group, err := s.GetGroupInfoByGroupId(ctx, groupId)
// if err != nil {
// return nil, err
// }
// ctx = group.WithContext(ctx)
//
// return ctx, nil
//}
//
//func (s *Service) WithPersonCtxOpt(ctx context.Context) (context.Context, error) {
// groupId, err := biz.NewGroupIdFromContext(ctx)
// if err != nil {
// return nil, err
// }
//
// memberId, _ := ctx.Value(api.Address).(string)
// if memberId == "" {
// return ctx, nil
// }
//
// person, err := s.GetPersonByMemberIdAndGroupId(ctx, memberId, groupId)
// if err != nil {
// return nil, err
// }
// ctx = person.WithContext(ctx)
//
// return ctx, nil
//}
//
//func (s *Service) WithAdminCtxOpt(ctx context.Context) (context.Context, error) {
// person, err := biz.NewGroupMemberFromContext(ctx)
// if err != nil {
// return nil, err
// }
//
// if err := person.IsAdmin(); err != nil {
// return nil, err
// }
//
// return ctx, nil
//}
//
//func (s *Service) WithOwnerCtxOpt(ctx context.Context) (context.Context, error) {
// person, err := biz.NewGroupMemberFromContext(ctx)
// if err != nil {
// return nil, err
// }
//
// if err := person.IsOwner(); err != nil {
// return nil, err
// }
//
// return ctx, nil
//}

View File

@@ -0,0 +1,258 @@
package service
import (
"context"
"github.com/pkg/errors"
"gitlab.33.cn/chat/dtalk/pkg/contextx"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
xrand "gitlab.33.cn/chat/dtalk/pkg/rand"
"gitlab.33.cn/chat/dtalk/service/group/model"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
//CreateGroupSvc 创建群, 返回群信息
func (s *Service) CreateGroupSvc(ctx context.Context, req *types.CreateGroupRequest) (res *types.CreateGroupResponse, err error) {
groupId, err := s.getLogId(context.Background())
if err != nil {
return nil, err
}
// 判断群人数
if err := s.CheckGroupMemberNum(convert.ToInt32(len(req.Members))+1, biz.GroupMaximum); err != nil {
return nil, err
}
// 创建群
nowTime := s.getNowTime()
groupMembers := make([]*db.GroupMember, 0, len(req.MemberIds)+1)
groupMembers = append(groupMembers, &db.GroupMember{
GroupId: groupId,
GroupMemberId: req.Owner.MemberId,
GroupMemberName: req.Owner.MemberName,
GroupMemberType: req.Owner.MemberType,
GroupMemberJoinTime: nowTime,
GroupMemberUpdateTime: nowTime,
})
for i := 0; i < len(req.MemberIds); i++ {
member := req.Members[i]
if member.MemberId == req.Owner.MemberId {
continue
}
groupMembers = append(groupMembers, &db.GroupMember{
GroupId: groupId,
GroupMemberId: member.MemberId,
GroupMemberName: member.MemberName,
GroupMemberType: member.MemberType,
GroupMemberJoinTime: nowTime,
GroupMemberUpdateTime: nowTime,
})
}
groupMarkId, err := s.getRandomGroupMarkId()
if err != nil {
return nil, err
}
group := &db.GroupInfo{
GroupId: groupId,
GroupMarkId: groupMarkId,
GroupName: req.Name,
GroupAvatar: req.Avatar,
GroupMemberNum: convert.ToInt32(len(groupMembers)),
GroupMaximum: biz.GroupMaximum,
GroupIntroduce: req.Introduce,
GroupStatus: biz.GroupStatusNormal,
GroupOwnerId: req.Owner.MemberId,
GroupJoinType: biz.GroupJoinTypeAny,
GroupMuteType: biz.GroupMuteTypeAny,
GroupFriendType: biz.GroupFriendTypeAllow,
GroupCreateTime: nowTime,
GroupUpdateTime: nowTime,
GroupAESKey: xrand.NewAESKey256(),
GroupPubName: req.Name,
GroupType: biz.GroupTypeNormal,
}
err = s.createGroup(ctx, group, groupMembers)
if err != nil {
return nil, err
}
res = &types.CreateGroupResponse{
GroupInfo: &types.GroupInfo{
Id: groupId,
IdStr: convert.ToString(groupId),
MarkId: groupMarkId,
Name: req.Name,
Avatar: req.Avatar,
Introduce: req.Introduce,
Owner: &req.Owner,
MemberNum: convert.ToInt32(1 + len(req.Members)),
Maximum: biz.GroupMaximum,
Status: biz.GroupStatusNormal,
CreateTime: nowTime,
JoinType: biz.GroupJoinTypeAny,
MuteType: biz.GroupMuteTypeAny,
FriendType: biz.GroupFriendTypeAllow,
MuteNum: 0,
PublicName: req.Name,
AESKey: group.GroupAESKey,
GroupType: biz.GroupTypeNormal,
},
Members: req.Members,
}
return res, nil
}
// getRandomGroupMarkId 得到不重复的 8 位数字群组 id
func (s *Service) getRandomGroupMarkId() (string, error) {
for {
groupMarkId := xrand.NewNumber(8)
if _, err := s.dao.GetGroupInfoByGroupMarkId(groupMarkId); err != nil {
if errors.Is(err, model.ErrRecordNotExist) {
return groupMarkId, nil
}
return "", err
}
}
}
// getLogId 由 generator 服务生成唯一 id
func (s *Service) getLogId(ctx context.Context) (id int64, err error) {
reply, err := s.idGenRPCClient.GetID()
if err != nil {
return 0, err
}
return reply, nil
}
// execGroupCreate 执行创建群操作
func (s *Service) execGroupCreate(groupInfo *db.GroupInfo, members []*db.GroupMember) error {
tx, err := s.dao.NewTx()
if err != nil {
return err
}
defer tx.RollBack()
if _, _, err = s.dao.InsertGroupInfo(tx, groupInfo); err != nil {
return err
}
if err = s.InsertGroupMembers(tx, members); err != nil {
return err
}
if err = tx.Commit(); err != nil {
return err
}
return nil
}
func (s *Service) createGroup(ctx context.Context, group *db.GroupInfo, groupMembers []*db.GroupMember) error {
log := s.GetLogWithTrace(ctx)
var err error
groupId := group.GroupId
groupMemberIds := make([]string, 0, len(groupMembers))
groupOwnerId := ""
for _, groupMember := range groupMembers {
if groupMember.GroupMemberType == biz.GroupMemberTypeOwner {
groupOwnerId = groupMember.GroupMemberId
continue
}
groupMemberIds = append(groupMemberIds, groupMember.GroupMemberId)
}
groupMemberIds = append(groupMemberIds, groupOwnerId)
if err = s.execGroupCreate(group, groupMembers); err != nil {
return err
}
go func() {
// 发送给 logic
if err = s.LogicNoticeJoin(contextx.ValueOnlyFrom(ctx), groupId, groupMemberIds); err != nil {
log.Error().Err(err).Msg("createGroup logic")
}
// 发送给 pusher
if err = s.PusherSignalJoin(contextx.ValueOnlyFrom(ctx), groupId, groupMemberIds); err != nil {
log.Error().Err(err).Msg("createGroup pusher")
}
if err = s.NoticeMsgSignInGroup(contextx.ValueOnlyFrom(ctx), groupId, s.GetOpe(ctx), groupMemberIds[0:len(groupMemberIds)-1]); err != nil {
log.Error().Err(err).Msg("createGroup alert")
}
}()
return nil
}
func (s *Service) CreateGroup(ctx context.Context, group *biz.GroupInfo, owner *biz.GroupMember, members []*biz.GroupMember) (int64, error) {
groupId, err := s.getLogId(ctx)
if err != nil {
return 0, err
}
groupMarkId, err := s.getRandomGroupMarkId()
if err != nil {
return 0, err
}
groupMemberNum := int32(1 + len(members))
if groupMemberNum > biz.GroupMaximum {
return 0, xerror.NewError(xerror.GroupMemberLimit)
}
groupPo := &db.GroupInfo{
GroupId: groupId,
GroupMarkId: groupMarkId,
GroupName: group.GroupName,
GroupAvatar: "",
GroupMemberNum: int32(1 + len(members)),
GroupMaximum: biz.GroupMaximum,
GroupIntroduce: "",
GroupStatus: biz.GroupStatusNormal,
GroupOwnerId: owner.GroupMemberId,
GroupJoinType: biz.GroupJoinTypeAny,
GroupMuteType: biz.GroupMuteTypeAny,
GroupFriendType: biz.GroupFriendTypeAllow,
GroupAESKey: xrand.NewAESKey256(),
GroupPubName: group.GroupName,
GroupType: group.GroupType,
}
if group.GroupType == biz.GroupTypeNormal {
groupPo.GroupJoinType = biz.GroupJoinTypeAny
} else {
groupPo.GroupJoinType = biz.GroupJoinTypeAdmin
}
ownerPo := &db.GroupMember{
GroupId: groupId,
GroupMemberId: owner.GroupMemberId,
GroupMemberName: owner.GroupMemberName,
GroupMemberType: biz.GroupMemberTypeOwner,
}
membersPo := make([]*db.GroupMember, 0, len(members))
membersPo = append(membersPo, ownerPo)
for _, member := range members {
membersPo = append(membersPo, &db.GroupMember{
GroupId: groupId,
GroupMemberId: member.GroupMemberId,
GroupMemberName: member.GroupMemberName,
GroupMemberType: biz.GroupMemberTypeNormal,
})
}
err = s.createGroup(ctx, groupPo, membersPo)
if err != nil {
return 0, err
}
return groupId, nil
}

View File

@@ -0,0 +1,76 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
func (s *Service) CreateGroupApplySvc(ctx context.Context, req *types.CreateGroupApplyReq) (res *types.CreateGroupApplyResp, err error) {
personId := req.PersonId
groupId := convert.ToInt64(req.Id)
_, err = s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
// 判断是否已经在群内
if isExit, err := s.CheckInGroup(personId, groupId); err != nil {
return nil, err
} else if isExit == true {
return nil, xerror.NewError(xerror.GroupMemberExist)
}
err = s.ExecCreateGroupApply(groupId, "", []string{personId}, req.ApplyNote)
if err != nil {
return nil, err
}
return &types.CreateGroupApplyResp{}, nil
}
func (s *Service) ExecCreateGroupApply(groupId int64, inviterId string, memberIds []string, applyNote string) error {
groupApplys := make([]*db.GroupApply, 0)
nowTime := s.getNowTime()
applyId, err := s.getLogId(context.Background())
if err != nil {
return err
}
for _, memberId := range memberIds {
groupApply := &db.GroupApply{
Id: applyId,
GroupId: groupId,
InviterId: inviterId,
MemberId: memberId,
ApplyNote: applyNote,
OperatorId: "",
ApplyStatus: biz.GroupApplyWait,
RejectReason: "",
CreateTime: nowTime,
UpdateTime: nowTime,
}
groupApplys = append(groupApplys, groupApply)
}
tx, err := s.dao.NewTx()
if err != nil {
return err
}
defer tx.RollBack()
err = s.dao.InsertGroupApplys(tx, groupApplys)
if err != nil {
return err
}
if err = tx.Commit(); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,37 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
func (s *Service) GetGroupApplyByIdSvc(ctx context.Context, req *types.GetGroupApplyByIdReq) (res *types.GetGroupApplysResp, err error) {
//personId := req.PersonId
applyId := convert.ToInt64(req.ApplyId)
groupApplyBiz, err := s.getGroupApplyById(applyId)
if err != nil {
return nil, err
}
return &types.GetGroupApplysResp{
GroupApplys: []*types.GroupApplyInfo{groupApplyBiz.ToTypes()},
}, nil
}
func (s *Service) getGroupApplyById(id int64) (*biz.GroupApplyBiz, error) {
groupApply, err := s.dao.GetGroupApplyById(id)
if err != nil {
return nil, err
}
if groupApply == nil {
return nil, xerror.NewError(xerror.GroupApplyNotExist)
}
return groupApply.ToBiz(), nil
}

View File

@@ -0,0 +1,39 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
func (s *Service) GetGroupApplysSvc(ctx context.Context, req *types.GetGroupApplysReq) (res *types.GetGroupApplysResp, err error) {
//personId := req.PersonId
groupId := convert.ToInt64(req.Id)
groupApplyBizs, err := s.getGroupApplys(groupId, req.Count, req.Offset)
if err != nil {
return nil, err
}
res = &types.GetGroupApplysResp{}
res.GroupApplys = make([]*types.GroupApplyInfo, 0)
for _, groupApplyBiz := range groupApplyBizs {
res.GroupApplys = append(res.GroupApplys, groupApplyBiz.ToTypes())
}
return res, nil
}
func (s *Service) getGroupApplys(groupId int64, limit, offset int32) ([]*biz.GroupApplyBiz, error) {
groupApplys, err := s.dao.GetGroupApplys(groupId, limit, offset)
if err != nil {
return nil, err
}
groupApplyBizs := make([]*biz.GroupApplyBiz, 0)
for _, groupApply := range groupApplys {
groupApplyBizs = append(groupApplyBizs, groupApply.ToBiz())
}
return groupApplyBizs, nil
}

View File

@@ -0,0 +1,43 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// GetGroupInfoHttp 查询群资料
func (s *Service) GetGroupInfoHttp(ctx context.Context, req *types.GetGroupInfoRequest) (res *types.GetGroupInfoResponse, err error) {
groupId := req.Id
personId := req.PersonId
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
personInfo, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, group.GroupId)
if err != nil {
return nil, err
}
ownerInfo, err := s.GetMemberByMemberIdAndGroupId(ctx, group.GroupOwnerId, group.GroupId)
if err != nil {
return nil, err
}
memberInfos, err := s.GetGroupMembersByGroupIdWithLimit(group.GroupId, 0, req.DisPlayNum)
if err != nil {
return nil, err
}
groupType := group.ToTypes(ownerInfo.ToTypes(), personInfo.ToTypes())
memberInfosType := make([]*types.GroupMember, 0)
for _, member := range memberInfos {
memberInfosType = append(memberInfosType, member.ToTypes())
}
res = &types.GetGroupInfoResponse{}
res.GroupInfo = groupType
res.Members = memberInfosType
return res, nil
}

View File

@@ -0,0 +1,60 @@
package service
import (
"context"
"errors"
"gitlab.33.cn/chat/dtalk/service/group/model"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
// GetGroupInfoByConditionSvc 通过搜索得到群列表
func (s *Service) GetGroupInfoByConditionSvc(ctx context.Context, req *types.GetGroupInfoByConditionReq) (res *types.GetGroupInfoByConditionResp, err error) {
//personId := req.PersonId
groups := make([]*biz.GroupInfo, 0)
switch req.Tp {
case 0:
groupInfo, err := s.dao.GetGroupInfoByGroupMarkId(req.Query)
if err != nil && !errors.Is(err, model.ErrRecordNotExist) {
return nil, err
}
if groupInfo != nil {
if err := groupInfo.IsNormal(); err != nil {
return nil, err
}
groups = append(groups, groupInfo)
}
case 1:
groupId := convert.ToInt64(req.Query)
groupInfo, err := s.dao.GetGroupInfoByGroupId(ctx, groupId)
if err != nil && !errors.Is(err, model.ErrRecordNotExist) {
return nil, err
}
if groupInfo != nil {
if err := groupInfo.IsNormal(); err != nil {
return nil, err
}
groups = append(groups, groupInfo)
}
}
groupBizInfos := make([]*types.GroupInfo, 0)
for _, group := range groups {
ownerInfo, err := s.GetMemberByMemberIdAndGroupId(ctx, group.GroupOwnerId, group.GroupId)
if err != nil {
return nil, err
}
groupBizInfo := group.ToTypes(ownerInfo.ToTypes(), nil)
groupBizInfos = append(groupBizInfos, groupBizInfo)
}
return &types.GetGroupInfoByConditionResp{
Groups: groupBizInfos,
}, nil
}

View File

@@ -0,0 +1,44 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// TODO check
// GetGroupListSvc 查询群列表
func (s *Service) GetGroupListSvc(ctx context.Context, req *types.GetGroupListRequest) (res *types.GetGroupListResponse, err error) {
personId := req.PersonId
groupIds, err := s.GetGroupIdsByMemberId(personId)
if err != nil {
return nil, err
}
res = &types.GetGroupListResponse{
Groups: make([]*types.GroupInfo, len(groupIds), len(groupIds)),
}
for i, id := range groupIds {
group, err := s.GetGroupInfoByGroupId(ctx, id)
if err != nil {
return nil, err
}
ownerInfo, err := s.GetMemberByMemberIdAndGroupId(ctx, group.GroupOwnerId, group.GroupId)
if err != nil {
return nil, err
}
personInfo, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, group.GroupId)
if err != nil {
return nil, err
}
groupType := group.ToTypes(ownerInfo.ToTypes(), personInfo.ToTypes())
res.Groups[i] = groupType
}
return res, nil
}

View File

@@ -0,0 +1,33 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// GetGroupMemberInfoSvc 查询群成员信息
func (s *Service) GetGroupMemberInfoSvc(ctx context.Context, req *types.GetGroupMemberInfoRequest) (res *types.GetGroupMemberInfoResponse, err error) {
groupId := req.Id
memberId := req.MemberId
personId := req.PersonId
_, err = s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
_, err = s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
member, err := s.GetMemberByMemberIdAndGroupId(ctx, memberId, groupId)
if err != nil {
return nil, err
}
res = &types.GetGroupMemberInfoResponse{}
res.GroupMember = member.ToTypes()
return res, nil
}

View File

@@ -0,0 +1,43 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
// GetGroupMemberListSvc 查询群成员列表
func (s *Service) GetGroupMemberListSvc(ctx context.Context, req *types.GetGroupMemberListRequest) (res *types.GetGroupMemberListResponse, err error) {
groupId := req.Id
personId := req.PersonId
_, err = s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
_, err = s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
groupMembers, err := s.GetMembersByGroupId(groupId)
if err != nil {
return nil, err
}
groupMemberTypes := make([]*types.GroupMember, 0)
for _, groupMember := range groupMembers {
groupMemberTypes = append(groupMemberTypes, groupMember.ToTypes())
}
res = &types.GetGroupMemberListResponse{
Id: groupId,
IdStr: convert.ToString(groupId),
Members: groupMemberTypes,
}
return res, nil
}

View File

@@ -0,0 +1,43 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// GetGroupPubInfoSvc 查询群资料
func (s *Service) GetGroupPubInfoSvc(ctx context.Context, req *types.GetGroupPubInfoRequest) (res *types.GetGroupPubInfoResponse, err error) {
groupId := req.Id
personId := req.PersonId
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
personInfo, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, group.GroupId)
if err != nil {
if xerror.NewError(xerror.GroupPersonNotExist).Error() != err.Error() {
return nil, err
}
}
ownerInfo, err := s.GetMemberByMemberIdAndGroupId(ctx, group.GroupOwnerId, group.GroupId)
if err != nil {
return nil, err
}
res = &types.GetGroupPubInfoResponse{}
var personType *types.GroupMember
if personInfo != nil {
personType = personInfo.ToTypes()
}
res.GroupInfo = group.ToTypes(ownerInfo.ToTypes(), personType)
if personInfo == nil {
res.GroupInfo.AESKey = ""
}
return res, nil
}

View File

@@ -0,0 +1,48 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// GetMuteListSvc 查询群内禁言列表
func (s *Service) GetMuteListSvc(ctx context.Context, req *types.GetMuteListRequest) (res *types.GetMuteListResponse, err error) {
groupId := req.Id
personId := req.PersonId
_, err = s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
muteList, err := s.GetGroupMembersMutedByGroupId(groupId)
if err != nil {
return nil, err
}
memberTypes := make([]*types.GroupMember, 0)
for _, member := range muteList {
memberTypes = append(memberTypes, member.ToTypes())
}
res = &types.GetMuteListResponse{Members: memberTypes}
return res, nil
}
// GetGroupMembersMutedByGroupId 查询群内被禁言的群成员信息
func (s *Service) GetGroupMembersMutedByGroupId(groupId int64) ([]*biz.GroupMember, error) {
muteList, err := s.dao.GetGroupMembersMutedByGroupId(groupId)
if err != nil {
return nil, err
}
return muteList, nil
}

View File

@@ -0,0 +1,102 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/pkg/contextx"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// GroupDisbandHttp 解散群
func (s *Service) GroupDisbandHttp(ctx context.Context, req *types.GroupDisbandRequest) (res *types.GroupDisbandResponse, err error) {
groupId := req.Id
personId := req.PersonId
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
// 只有群主可以解散群
if err = person.IsOwner(); err != nil {
return nil, err
}
err = s.GroupDisband(ctx, groupId, personId)
if err != nil {
return nil, err
}
return res, nil
}
func (s *Service) GroupDisband(ctx context.Context, groupId int64, opeId string) error {
var err error
log := s.GetLogWithTrace(ctx)
// 执行解散群
if err = s.ExecGroupDisband(groupId); err != nil {
return err
}
go func() {
// 发送给 alert
if err = s.NoticeMsgDeleteGroup(contextx.ValueOnlyFrom(ctx), groupId, opeId); err != nil {
log.Error().Err(err).Msg("GroupDisband alert")
}
// 发送给 pusher
if err = s.PusherSignalDel(contextx.ValueOnlyFrom(ctx), groupId); err != nil {
log.Error().Err(err).Msg("GroupDisband pusher")
}
// 发送给 logic
if err = s.LogicNoticeDel(contextx.ValueOnlyFrom(ctx), groupId); err != nil {
log.Error().Err(err).Msg("GroupDisband logic")
}
}()
return nil
}
// ExecGroupDisband 执行解散群操作
func (s *Service) ExecGroupDisband(groupId int64) error {
nowTime := s.getNowTime()
groupMembers, err := s.GetMembersByGroupId(groupId)
if err != nil {
return err
}
tx, err := s.dao.NewTx()
if err != nil {
return err
}
defer tx.RollBack()
groupInfo := &db.GroupInfo{
GroupId: groupId,
GroupStatus: biz.GroupStatusDisBand,
GroupUpdateTime: nowTime,
}
if _, _, err = s.dao.UpdateGroupInfoStatusWithTx(tx, groupInfo); err != nil {
return err
}
for _, member := range groupMembers {
groupMemberInfo := &db.GroupMember{
GroupId: groupId,
GroupMemberId: member.GroupMemberId,
GroupMemberUpdateTime: nowTime,
GroupMemberType: biz.GroupMemberTypeOther,
}
if _, _, err = s.dao.UpdateGroupMemberTypeWithTx(tx, groupMemberInfo); err != nil {
return err
}
}
if err = tx.Commit(); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,78 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/pkg/contextx"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// GroupExitHttp 退群
func (s *Service) GroupExitHttp(ctx context.Context, req *types.GroupExitRequest) (res *types.GroupExitResponse, err error) {
group, err := s.GetGroupInfoByGroupId(ctx, req.Id)
if err != nil {
return nil, err
}
//person, err := s.GetPersonByMemberIdAndGroupId(personId, groupId)
person, err := s.GetPersonByMemberIdAndGroupId(ctx, req.PersonId, req.Id)
if err != nil {
return nil, err
}
if err = person.IsOwner(); err == nil {
return nil, xerror.NewError(xerror.GroupOwnerExit)
}
err = s.ExitGroup(ctx, group, person)
if err != nil {
return nil, err
}
return res, nil
}
func (s *Service) ExitGroup(ctx context.Context, group *biz.GroupInfo, member *biz.GroupMember) error {
groupId := group.GroupId
memberId := member.GroupMemberId
log := s.GetLogWithTrace(ctx)
// 执行退群
if err := s.ExecGroupExit(ctx, groupId, memberId); err != nil {
return err
}
// 更新群人数
_, err := s.UpdateGroupInfoMemberNum(ctx, groupId)
if err != nil {
log.Error().Err(err).Msg("GroupExitHttp exec")
}
go func() {
// 发送给 pusher
if err = s.PusherSignalLeave(contextx.ValueOnlyFrom(ctx), groupId, []string{memberId}); err != nil {
log.Error().Err(err).Msg("GroupExitHttp pusher")
}
// 发送给 logic
if err = s.LogicNoticeLeave(contextx.ValueOnlyFrom(ctx), groupId, []string{memberId}); err != nil {
log.Error().Err(err).Msg("GroupExitHttp logic")
}
// 发送给 alert
if err = s.NoticeMsgSignOutGroup(contextx.ValueOnlyFrom(ctx), groupId, memberId); err != nil {
log.Error().Err(err).Msg("GroupExitHttp alert")
}
}()
return nil
}
// ExecGroupExit 执行退群操作
func (s *Service) ExecGroupExit(ctx context.Context, groupId int64, memberId string) error {
err := s.dao.UpdateGroupMemberType(ctx, groupId, memberId, biz.GroupMemberTypeOther)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,118 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/pkg/contextx"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// GroupRemoveSvc 踢人
func (s *Service) GroupRemoveSvc(ctx context.Context, req *types.GroupRemoveRequest) (res *types.GroupRemoveResponse, err error) {
groupId := req.Id
memberIds := req.MemberIds
personId := req.PersonId
// 判断一下该群是否存在
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
// 判断踢人者权限
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
// 过滤可以踢人的列表
needDeleteMembers := s.GetFilteredGroupMembers(ctx, group, memberIds)
if len(needDeleteMembers) == 0 {
return &types.GroupRemoveResponse{MemberNum: group.GroupMemberNum}, nil
}
canRemoveMemberIds := make([]string, 0)
canRemoveMembers := make([]*biz.GroupMember, 0)
for _, member := range needDeleteMembers {
if err := person.RemoveOneMember(member); err != nil {
return nil, err
}
canRemoveMemberIds = append(canRemoveMemberIds, member.GroupMemberId)
canRemoveMembers = append(canRemoveMembers, member)
}
// 执行踢人
if err = s.RemoveGroupMembers(ctx, group, canRemoveMembers); err != nil {
return nil, err
}
res = &types.GroupRemoveResponse{
MemberIds: canRemoveMemberIds,
}
return res, nil
}
// RemoveGroupMembers 执行踢人操作
func (s *Service) RemoveGroupMembers(ctx context.Context, group *biz.GroupInfo, members []*biz.GroupMember) error {
if len(members) == 0 {
return nil
}
groupId := group.GroupId
memberIds := make([]string, 0, len(members))
for _, member := range members {
memberIds = append(memberIds, member.GroupMemberId)
}
log := s.GetLogWithTrace(ctx)
nowTime := s.getNowTime()
tx, err := s.dao.NewTx()
if err != nil {
return err
}
defer tx.RollBack()
for _, memberId := range memberIds {
groupMemberInfo := &db.GroupMember{
GroupId: groupId,
GroupMemberId: memberId,
GroupMemberUpdateTime: nowTime,
GroupMemberType: biz.GroupMemberTypeOther,
}
if _, _, err = s.dao.UpdateGroupMemberTypeWithTx(tx, groupMemberInfo); err != nil {
return err
}
}
if err = tx.Commit(); err != nil {
return err
}
// 更新群人数
_, err = s.UpdateGroupInfoMemberNum(ctx, groupId)
if err != nil {
log.Error().Err(err).Msg("GroupRemoveSvc")
}
go func() {
// 发送给 alert
if err = s.NoticeMsgKickOutGroup(contextx.ValueOnlyFrom(ctx), groupId, s.GetOpe(ctx), memberIds); err != nil {
log.Error().Err(err).Msg("GroupRemoveSvc alert")
}
// 发送个 pusher
if err = s.PusherSignalLeave(contextx.ValueOnlyFrom(ctx), groupId, memberIds); err != nil {
log.Error().Msg("GroupRemoveSvc pusher")
}
// 发送给 logic
if err = s.LogicNoticeLeave(contextx.ValueOnlyFrom(ctx), groupId, memberIds); err != nil {
log.Error().Msg("GroupRemoveSvc logic")
}
}()
return nil
}

View File

@@ -0,0 +1,181 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
// InviteGroupMembersSvc 邀请新群员
// 加群设置为 Any
// - 邀请人为空, 直接加入
// - 邀请人不为空, 直接加入
// 加群设置为 Apply
// - 邀请人为空, 走审批流程
// - 邀请人为普通人, 走审批流程
// - 邀请人为管理员, 直接加入
// 加群设置为 Admin
// - 邀请人为空, 拒绝加入
// - 邀请人为普通人, 拒绝加入
// - 邀请人为管理员, 直接加入
func (s *Service) InviteGroupMembersSvc(ctx context.Context, req *types.InviteGroupMembersRequest) (res *types.InviteGroupMembersResponse, err error) {
//personId := req.Inviter.MemberId
groupId := req.Id
group, err := s.GetGroupInfoByGroupId(ctx, req.Id)
if err != nil {
return nil, err
}
if req.Inviter.MemberId == "" {
if group.GroupJoinType == biz.GroupJoinTypeAny {
return s.inviteMember(ctx, group, req)
} else if group.GroupJoinType == biz.GroupJoinTypeApply {
return s.invite2apply(req.NewMemberIds, groupId, "")
}
return nil, xerror.NewError(xerror.GroupInvitePermissionDenied)
}
// 得到邀请人信息
inviter, err := s.GetPersonByMemberIdAndGroupId(ctx, req.Inviter.MemberId, groupId)
if err != nil {
return nil, err
}
switch inviter.TryInvite(group) {
case biz.InviteOk:
return s.inviteMember(ctx, group, req)
case biz.InviteApply:
return s.invite2apply(req.NewMemberIds, groupId, inviter.GroupMemberId)
case biz.InviteFail:
return nil, xerror.NewError(xerror.GroupInvitePermissionDenied)
}
return nil, xerror.NewError(xerror.CodeInnerError)
}
// ExecInviteGroupMembers 执行邀请群成员操作
//func (s *Service) ExecInviteGroupMembers(members []*db.GroupMember) error {
// tx, err := s.dao.NewTx()
// if err != nil {
// return err
// }
//
// defer tx.RollBack()
//
// if err = s.InsertGroupMembers(tx, members); err != nil {
// return err
// }
//
// if err = tx.Commit(); err != nil {
// return err
// }
//
// return nil
//}
func (s *Service) invite2apply(MemberIds []string, groupId int64, inviterId string) (res *types.InviteGroupMembersResponse, err error) {
newMemberIds := []string{}
for _, memberId := range MemberIds {
// 判断是否已经在群内
if isExit, err := s.CheckInGroup(memberId, groupId); err != nil {
continue
} else if isExit == true {
continue
}
newMemberIds = append(newMemberIds, memberId)
}
if len(newMemberIds) == 0 {
return nil, xerror.NewError(xerror.GroupInviteNoMembers)
}
err = s.ExecCreateGroupApply(groupId, inviterId, newMemberIds, "")
if err != nil {
return nil, err
}
return &types.InviteGroupMembersResponse{}, nil
}
func (s *Service) inviteMember(ctx context.Context, group *biz.GroupInfo, req *types.InviteGroupMembersRequest) (res *types.InviteGroupMembersResponse, err error) {
groupId := group.GroupId
personId := req.Inviter.MemberId
// 判断群人数上限
if err = group.TryJoin(int32(len(req.NewMembers))); err != nil {
return nil, err
}
// 插入新群员
nowTime := s.getNowTime()
newMembers := make([]*db.GroupMember, 0)
for _, member := range req.NewMembers {
// 判断是否已经在群内
if isExit, err := s.CheckInGroup(member.MemberId, groupId); err != nil {
continue
} else if isExit == true {
continue
}
newMembers = append(newMembers, &db.GroupMember{
GroupId: groupId,
GroupMemberId: member.MemberId,
GroupMemberName: member.MemberName,
GroupMemberType: member.MemberType,
GroupMemberJoinTime: nowTime,
GroupMemberUpdateTime: nowTime,
})
}
// 被邀请的人都已经在本群中
if len(newMembers) == 0 {
err = xerror.NewError(xerror.GroupInviteNoMembers)
return nil, err
}
if err = s.AddGroupMembers(ctx, group.GroupId, newMembers, personId); err != nil {
return nil, err
}
// ? 不知道有没有用
res = &types.InviteGroupMembersResponse{
Id: req.Id,
IdStr: convert.ToString(groupId),
MemberNum: group.GroupMemberNum + int32(len(newMembers)),
//Inviter: req.Inviter,
//NewMembers: model.GroupMemberConvertGroupMemberInfo(newMembers),
}
return res, nil
}
func (s *Service) InviteMembers(ctx context.Context, group *biz.GroupInfo, newMemberIds []string) error {
groupId := group.GroupId
// 判断群人数上限
if err := group.TryJoin(int32(len(newMemberIds))); err != nil {
return err
}
// 插入新群员
members := make([]*biz.GroupMember, 0, len(newMemberIds))
for _, memberId := range newMemberIds {
members = append(members, &biz.GroupMember{
GroupId: groupId,
GroupMemberId: memberId,
GroupMemberName: "",
GroupMemberType: biz.GroupTypeNormal,
})
}
err := s.AddMembers(ctx, group, members)
if err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,154 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
)
// JoinGroupSvc 加入群聊, grpc 专属
//func (s *Service) JoinGroupSvc(ctx context.Context, req *types.JoinGroupReq) (res *types.JoinGroupResp, err error) {
// personId := req.PersonId
// groupId := req.Id
//
// group, err := s.GetGroupInfoByGroupId(ctx, groupId)
// if err != nil {
// return nil, err
// }
//
// // 判断群人数上限
// if err = group.TryJoin(1); err != nil {
// return nil, err
// }
//
// // 判断是否已经在群内
// if isExit, err := s.CheckInGroup(personId, groupId); err != nil {
// return nil, err
// } else if isExit == true {
// return nil, xerror.NewError(xerror.GroupInviteMemberExist)
// }
//
// nowTime := s.getNowTime()
// newMember := &db.GroupMember{
// GroupId: groupId,
// GroupMemberId: personId,
// GroupMemberName: "",
// GroupMemberType: 0,
// GroupMemberJoinTime: nowTime,
// GroupMemberUpdateTime: nowTime,
// }
//
// if err = s.AddGroupMembers(ctx, group.GroupId, []*db.GroupMember{newMember}, group.GroupOwnerId); err != nil {
// return nil, err
// }
//
// res = &types.JoinGroupResp{
// Id: groupId,
// IdStr: convert.ToString(groupId),
// }
//
// return
//}
// ExecJoinGroupMembers 执行邀请群成员操作
func (s *Service) ExecJoinGroupMembers(members []*db.GroupMember) error {
tx, err := s.dao.NewTx()
if err != nil {
return err
}
defer tx.RollBack()
if err = s.InsertGroupMembers(tx, members); err != nil {
return err
}
if err = tx.Commit(); err != nil {
return err
}
return nil
}
func (s *Service) GetFilteredGroupMembers(ctx context.Context, group *biz.GroupInfo, memberIds []string) []*biz.GroupMember {
members := make([]*biz.GroupMember, 0, len(memberIds))
for _, memberId := range memberIds {
member, err := s.GetMemberByMemberIdAndGroupId(ctx, memberId, group.GroupId)
if err != nil {
continue
}
members = append(members, member)
}
return members
}
// FilteredGroupMembers 过滤已经在群里的成员
func (s *Service) FilteredGroupMembers(members []*biz.GroupMember) []*biz.GroupMember {
newMembers := make([]*biz.GroupMember, 0)
for _, member := range members {
// 判断是否已经在群内
if isExit, err := s.CheckInGroup(member.GroupMemberId, member.GroupId); err != nil {
continue
} else if isExit == true {
continue
}
newMembers = append(newMembers, member)
}
return newMembers
}
func (s *Service) AddMembers(ctx context.Context, group *biz.GroupInfo, members []*biz.GroupMember) error {
members = s.FilteredGroupMembers(members)
if len(members) == 0 {
return nil
}
nowTime := s.getNowTime()
newMembers := make([]*db.GroupMember, 0, len(members))
for _, member := range members {
newMembers = append(newMembers, &db.GroupMember{
GroupId: member.GroupId,
GroupMemberId: member.GroupMemberId,
GroupMemberName: member.GroupMemberName,
GroupMemberType: member.GroupMemberType,
GroupMemberJoinTime: nowTime,
GroupMemberUpdateTime: nowTime,
})
}
if err := s.AddGroupMembers(ctx, group.GroupId, newMembers, s.GetOpe(ctx)); err != nil {
return err
}
return nil
}
func (s *Service) JoinGroups(ctx context.Context, members []*biz.GroupMember) {
log := s.GetLogWithTrace(ctx)
members = s.FilteredGroupMembers(members)
if len(members) == 0 {
return
}
nowTime := s.getNowTime()
for _, member := range members {
newMember := &db.GroupMember{
GroupId: member.GroupId,
GroupMemberId: member.GroupMemberId,
GroupMemberName: member.GroupMemberName,
GroupMemberType: member.GroupMemberType,
GroupMemberJoinTime: nowTime,
GroupMemberUpdateTime: nowTime,
}
if err := s.AddGroupMembers(ctx, member.GroupId, []*db.GroupMember{newMember}, s.GetOpe(ctx)); err != nil {
log.Error().Err(err).Msg("JoinGroups")
}
}
}

View File

@@ -0,0 +1,33 @@
package service
import (
"gitlab.33.cn/chat/dtalk/pkg/rand"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
)
// MaintainGroupAESKey 给旧的群设置 aes key
func (s *Service) MaintainGroupAESKey() error {
// 得到group列表
groups, err := s.dao.GetAllGroupInfo()
if err != nil {
s.log.Error().Err(err).Msg("GetAllGroupInfo")
return err
}
for _, group := range groups {
if group.AESKey == "" {
groupPo := &db.GroupInfo{
GroupId: group.GroupId,
GroupName: group.GroupName,
GroupAESKey: rand.NewAESKey256(),
GroupPubName: group.GroupName,
}
_, _, err := s.dao.MaintainAESKeyAndPubName(groupPo)
if err != nil {
s.log.Error().Err(err).Interface("groupPo", groupPo).Msg("MaintainAESKeyAndPubName")
}
}
}
return nil
}

View File

@@ -0,0 +1,45 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
"gitlab.33.cn/utils/go-kit/convert"
)
func (s *Service) RejectGroupApplySvc(ctx context.Context, req *types.RejectGroupApplyReq) (res *types.RejectGroupApplyResp, err error) {
personId := req.PersonId
groupId := convert.ToInt64(req.Id)
applyId := convert.ToInt64(req.ApplyId)
// 查询审批详情
groupApply, err := s.getGroupApplyById(applyId)
if err != nil {
return nil, err
}
// 判断审批是否被处理过
if err = groupApply.IsWait(); err != nil {
return nil, err
}
// 查询操作人详情并判断是否有权限操作
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
// 处理审批
groupApply.ApplyStatus = biz.GroupApplyReject
groupApply.OperatorId = personId
err = s.updateGroupApply(groupApply)
if err != nil {
return nil, err
}
return &types.RejectGroupApplyResp{}, nil
}

View File

@@ -0,0 +1,105 @@
package service
import (
"context"
"fmt"
"gitlab.33.cn/chat/dtalk/pkg/api"
"time"
"gitlab.33.cn/chat/dtalk/pkg/api/trace"
"gitlab.33.cn/chat/dtalk/pkg/logger"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"github.com/rs/zerolog"
"gitlab.33.cn/chat/dtalk/pkg/naming"
"gitlab.33.cn/chat/dtalk/pkg/net/grpc"
idgen "gitlab.33.cn/chat/dtalk/service/generator/api"
"gitlab.33.cn/chat/dtalk/service/group/config"
"gitlab.33.cn/chat/dtalk/service/group/dao"
answer "gitlab.33.cn/chat/dtalk/service/record/answer/api"
logic "gitlab.33.cn/chat/im/api/logic/grpc"
"google.golang.org/grpc/resolver"
)
type Service struct {
log zerolog.Logger
cfg *config.Config
dao *dao.Dao
idGenRPCClient *idgen.Client
logicClient logic.LogicClient
answerClient *answer.Client
}
var srvName = "group/srv"
func New(cfg *config.Config) *Service {
s := &Service{
log: logger.New(cfg.Env, srvName),
cfg: cfg,
dao: dao.New(cfg),
idGenRPCClient: idgen.New(cfg.IdGenRPCClient.RegAddrs, cfg.IdGenRPCClient.Schema, cfg.IdGenRPCClient.SrvName, time.Duration(cfg.IdGenRPCClient.Dial)),
logicClient: newLogicClient(cfg),
answerClient: answer.New(cfg.AnswerRPCClient.RegAddrs, cfg.AnswerRPCClient.Schema, cfg.AnswerRPCClient.SrvName, time.Duration(cfg.AnswerRPCClient.Dial)),
}
initGroupDefault(cfg.GroupInfoConfig)
return s
}
func newLogicClient(cfg *config.Config) logic.LogicClient {
rb := naming.NewResolver(cfg.LogicRPCClient.RegAddrs, cfg.LogicRPCClient.Schema)
resolver.Register(rb)
addr := fmt.Sprintf("%s:///%s", cfg.LogicRPCClient.Schema, cfg.LogicRPCClient.SrvName) // "schema://[authority]/service"
fmt.Println("logic rpc client call addr:", addr)
conn, err := grpc.NewGRPCConn(addr, time.Duration(cfg.LogicRPCClient.Dial))
if err != nil {
panic(err)
}
return logic.NewLogicClient(conn)
}
func (s *Service) Ping() error {
return nil
}
func (s Service) Config() *config.Config {
return s.cfg
}
func initGroupDefault(cfg *config.GroupDefault) {
if cfg.GroupMaximum < 200 {
cfg.GroupMaximum = 200
}
if cfg.GroupMaximum > 2000 {
cfg.GroupMaximum = 2000
}
biz.GroupMaximum = cfg.GroupMaximum
if cfg.AdminNum < 10 {
cfg.AdminNum = 10
}
if cfg.AdminNum > 10 {
cfg.AdminNum = 10
}
biz.AdminNum = cfg.AdminNum
}
func (s *Service) GetLog() zerolog.Logger {
return s.log
}
func (s *Service) GetLogWithTrace(ctx context.Context) zerolog.Logger {
logId := s.GetTrace(ctx)
return s.log.With().Str("trace", logId).Logger()
}
func (s *Service) GetTrace(ctx context.Context) string {
return trace.NewTraceIdWithContext(ctx)
}
func (s *Service) GetOpe(ctx context.Context) string {
return api.NewAddrWithContext(ctx)
}

View File

@@ -0,0 +1,134 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// SetAdminSvc 设置管理员
func (s *Service) SetAdminSvc(ctx context.Context, req *types.SetAdminRequest) (res *types.SetAdminResponse, err error) {
groupId := req.Id
personId := req.PersonId
memberId := req.MemberId
memberType := req.MemberType
log := s.GetLogWithTrace(ctx)
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
// 只有群主可以设置管理员
if personId != group.GroupOwnerId || person.GroupMemberType != biz.GroupMemberTypeOwner || memberId == personId {
err = xerror.NewError(xerror.GroupOwnerSetAdmin)
return nil, err
}
_, err = s.GetMemberByMemberIdAndGroupId(ctx, memberId, groupId)
if err != nil {
return nil, err
}
memberType, err = s.CheckSetAdminType(memberType)
if err != nil {
return nil, err
}
if err = group.TrySetAdmin(); memberType == biz.GroupMemberTypeAdmin && err != nil {
return nil, err
}
if err = s.UpdateGroupMemberType(ctx, groupId, memberId, memberType); err != nil {
return nil, err
}
// 发送给 pusher
if err = s.PusherSignalMemberType(ctx, groupId, memberId, memberType); err != nil {
log.Error().Err(err).Msg("SetAdminSvc pusher")
}
if memberType == biz.GroupMuteTypeAdmin {
// 解除新管理员禁言
nowTime := s.getNowTime()
groupMemberMute := make([]*db.GroupMemberMute, 1, 1)
groupMemberMute[0] = &db.GroupMemberMute{
GroupId: groupId,
GroupMemberId: memberId,
GroupMemberMuteTime: 0,
GroupMemberMuteUpdateTime: nowTime,
}
if err = s.execSetMemberMuteTimes(ctx, groupMemberMute); err != nil {
return nil, err
}
// 发送给 pusher
if err = s.PusherSignalMemberMuteTime(ctx, groupId, []string{memberId}, 0); err != nil {
log.Error().Err(err).Msg("UpdateMembersMuteTimeSvc pusher")
}
}
return res, nil
}
// CheckSetAdminType 检查SetAdmin是否合法
func (s *Service) CheckSetAdminType(memberType int32) (int32, error) {
switch memberType {
case biz.GroupMemberTypeNormal:
return biz.GroupMemberTypeNormal, nil
case biz.GroupMuteTypeAdmin:
return biz.GroupMemberTypeAdmin, nil
default:
return 0, xerror.NewError(xerror.ParamsError)
}
}
// UpdateGroupMemberType 更新群成员类型
func (s *Service) UpdateGroupMemberType(ctx context.Context, groupId int64, memberId string, memberType int32) error {
err := s.dao.UpdateGroupMemberType(ctx, groupId, memberId, memberType)
if err != nil {
return err
}
return nil
}
func (s *Service) SetAdmin(ctx context.Context, group *biz.GroupInfo, member *biz.GroupMember, memberType int32) error {
log := s.GetLogWithTrace(ctx)
groupId := group.GroupId
memberId := member.GroupMemberId
if err := s.UpdateGroupMemberType(ctx, groupId, memberId, memberType); err != nil {
return err
}
// 发送给 pusher
if err := s.PusherSignalMemberType(ctx, groupId, memberId, memberType); err != nil {
log.Error().Err(err).Msg("SetAdmin pusher")
}
if memberType == biz.GroupMuteTypeAdmin {
// 解除新管理员禁言
groupMemberMute := make([]*db.GroupMemberMute, 1, 1)
groupMemberMute[0] = &db.GroupMemberMute{
GroupId: groupId,
GroupMemberId: memberId,
GroupMemberMuteTime: 0,
}
if err := s.execSetMemberMuteTimes(ctx, groupMemberMute); err != nil {
log.Error().Err(err).Msg("execSetMemberMuteTimes pusher")
}
// 发送给 pusher
if err := s.PusherSignalMemberMuteTime(ctx, groupId, []string{memberId}, 0); err != nil {
log.Error().Err(err).Msg("PusherSignalMemberMuteTime pusher")
}
}
return nil
}

View File

@@ -0,0 +1,59 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// UpdateGroupAvatarSvc 更新群头像
func (s *Service) UpdateGroupAvatarSvc(ctx context.Context, req *types.UpdateGroupAvatarRequest) (res *types.UpdateGroupAvatarResponse, err error) {
groupId := req.Id
personId := req.PersonId
groupAvatar := req.Avatar
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := s.UpdateGroupAvatar(ctx, group, groupAvatar); err != nil {
return nil, err
}
return res, nil
}
// updateGroupAvatar 更新db群头像
func (s *Service) updateGroupAvatar(ctx context.Context, groupId int64, avatar string) error {
err := s.dao.UpdateGroupInfoAvatar(ctx, groupId, avatar)
if err != nil {
return err
}
return nil
}
func (s *Service) UpdateGroupAvatar(ctx context.Context, group *biz.GroupInfo, avatar string) error {
log := s.GetLogWithTrace(ctx)
groupId := group.GroupId
if err := s.updateGroupAvatar(ctx, groupId, avatar); err != nil {
return err
}
// 发送给 pusher
if err := s.PusherSignalGroupAvatar(ctx, groupId, avatar); err != nil {
log.Error().Err(err).Msg("UpdateGroupAvatar pusher")
}
return nil
}

View File

@@ -0,0 +1,77 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// UpdateGroupFriendTypeSvc 更新群内加好友设置
func (s *Service) UpdateGroupFriendTypeSvc(ctx context.Context, req *types.UpdateGroupFriendTypeRequest) (res *types.UpdateGroupFriendTypeResponse, err error) {
groupId := req.Id
personId := req.PersonId
friendType := req.FriendType
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := s.UpdateGroupFriendType(ctx, group, friendType); err != nil {
return nil, err
}
return res, nil
}
// CheckGroupFriendType 检查friendType是否合法
func (s *Service) CheckGroupFriendType(friendType int32) (int32, error) {
switch friendType {
case biz.GroupFriendTypeAllow:
return biz.GroupFriendTypeAllow, nil
case biz.GroupFriendTypeDeny:
return biz.GroupFriendTypeDeny, nil
default:
return 0, xerror.NewError(xerror.ParamsError)
}
}
// updateGroupFriendType 更新群内加好友设置
func (s *Service) updateGroupFriendType(ctx context.Context, groupId int64, friendType int32) error {
err := s.dao.UpdateGroupInfoFriendType(ctx, groupId, friendType)
if err != nil {
return err
}
return nil
}
func (s *Service) UpdateGroupFriendType(ctx context.Context, group *biz.GroupInfo, friendType int32) error {
log := s.GetLogWithTrace(ctx)
groupId := group.GroupId
friendType, err := s.CheckGroupFriendType(friendType)
if err != nil {
return err
}
if err = s.updateGroupFriendType(ctx, groupId, friendType); err != nil {
return err
}
// 发送给 pusher
if err = s.PusherSignalFriendType(ctx, groupId, friendType); err != nil {
log.Error().Err(err).Msg("UpdateGroupFriendTypeSvc pusher")
}
return nil
}

View File

@@ -0,0 +1,80 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// UpdateGroupJoinTypeSvc 更新加群设置
// todo 改造完后就弃用
func (s *Service) UpdateGroupJoinTypeSvc(ctx context.Context, req *types.UpdateGroupJoinTypeRequest) (res *types.UpdateGroupJoinTypeResponse, err error) {
groupId := req.Id
personId := req.PersonId
joinType := req.JoinType
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := s.UpdateGroupJoinType(ctx, group, joinType); err != nil {
return nil, err
}
return res, nil
}
// CheckGroupJoinType 检查joinType是否合法
func (s *Service) CheckGroupJoinType(joinType int32) (int32, error) {
switch joinType {
case biz.GroupJoinTypeAny:
return biz.GroupJoinTypeAny, nil
case biz.GroupJoinTypeAdmin:
return biz.GroupJoinTypeAdmin, nil
case biz.GroupJoinTypeApply:
return biz.GroupJoinTypeApply, nil
default:
return 0, xerror.NewError(xerror.ParamsError)
}
}
// updateGroupJoinType 更新加群设置
func (s *Service) updateGroupJoinType(ctx context.Context, groupId int64, joinType int32) error {
err := s.dao.UpdateGroupInfoJoinType(ctx, groupId, joinType)
if err != nil {
return err
}
return nil
}
func (s *Service) UpdateGroupJoinType(ctx context.Context, group *biz.GroupInfo, joinType int32) error {
log := s.GetLogWithTrace(ctx)
groupId := group.GroupId
joinType, err := s.CheckGroupJoinType(joinType)
if err != nil {
return err
}
if err = s.updateGroupJoinType(ctx, groupId, joinType); err != nil {
return err
}
// 发送给 pusher
if err = s.PusherSignalJoinType(ctx, groupId, joinType); err != nil {
log.Error().Err(err).Msg("UpdateGroupJoinType pusher")
}
return nil
}

View File

@@ -0,0 +1,82 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// UpdateGroupMuteTypeSvc 更新群禁言设置
func (s *Service) UpdateGroupMuteTypeSvc(ctx context.Context, req *types.UpdateGroupMuteTypeRequest) (res *types.UpdateGroupMuteTypeResponse, err error) {
groupId := req.Id
personId := req.PersonId
muteType := req.MuteType
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := s.UpdateGroupMuteType(ctx, group, muteType); err != nil {
return nil, err
}
return res, nil
}
// CheckGroupMuteType 检查muteType是否合法
func (s *Service) CheckGroupMuteType(muteType int32) (int32, error) {
switch muteType {
case biz.GroupMuteTypeAny:
return biz.GroupMuteTypeAny, nil
case biz.GroupMuteTypeAdmin:
return biz.GroupMuteTypeAdmin, nil
default:
return 0, xerror.NewError(xerror.ParamsError)
}
}
// updateGroupMuteType 更新群禁言设置
func (s *Service) updateGroupMuteType(ctx context.Context, groupId int64, muteType int32) error {
err := s.dao.UpdateGroupInfoMuteType(ctx, groupId, muteType)
if err != nil {
return err
}
return nil
}
func (s *Service) UpdateGroupMuteType(ctx context.Context, group *biz.GroupInfo, muteType int32) error {
log := s.GetLogWithTrace(ctx)
groupId := group.GroupId
muteType, err := s.CheckGroupMuteType(muteType)
if err != nil {
return err
}
if err = s.updateGroupMuteType(ctx, groupId, muteType); err != nil {
return err
}
// 发送给 pusher
if err = s.PusherSignalMuteType(ctx, groupId, muteType); err != nil {
log.Error().Err(err).Msg("UpdateGroupMuteType pusher")
}
// 发送给 alert
if err = s.NoticeMsgUpdateGroupMuted(ctx, groupId, s.GetOpe(ctx), muteType); err != nil {
log.Error().Err(err).Msg("UpdateGroupMuteType alert")
}
return nil
}

View File

@@ -0,0 +1,76 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// UpdateGroupNameSvc 更新群名称
func (s *Service) UpdateGroupNameSvc(ctx context.Context, req *types.UpdateGroupNameRequest) (res *types.UpdateGroupNameResponse, err error) {
groupId := req.Id
personId := req.PersonId
groupName := req.Name
groupPubName := req.PublicName
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
if err := s.UpdateGroupName(ctx, group, groupName, groupPubName); err != nil {
return nil, err
}
return res, nil
}
// updateGroupInfoName 更新群名称
func (s *Service) updateGroupInfoName(ctx context.Context, groupId int64, name, publicName string) error {
err := s.dao.UpdateGroupInfoName(ctx, groupId, name, publicName)
if err != nil {
return err
}
return nil
}
func (s *Service) UpdateGroupName(ctx context.Context, group *biz.GroupInfo, name, pubName string) error {
log := s.GetLogWithTrace(ctx)
groupId := group.GroupId
groupNameAlert := name
groupName := name
groupPubName := pubName
if groupName == "" {
groupName = group.GroupName
}
if groupPubName == "" {
groupPubName = group.GroupPubName
}
if err := s.updateGroupInfoName(ctx, groupId, groupName, groupPubName); err != nil {
return err
}
// 发送给 pusher
if err := s.PusherSignalGroupName(ctx, groupId, groupNameAlert); err != nil {
log.Error().Err(err).Msg("UpdateGroupNameSvc pusher")
}
// 发送给 alert
if err := s.NoticeMsgUpdateGroupName(ctx, groupId, s.GetOpe(ctx), groupNameAlert); err != nil {
log.Error().Err(err).Msg("UpdateGroupNameSvc alert")
}
return nil
}

View File

@@ -0,0 +1,51 @@
package service
import (
"context"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// UpdateMemberNameSvc 更新群成员昵称
func (s *Service) UpdateMemberNameSvc(ctx context.Context, req *types.UpdateGroupMemberNameRequest) (res *types.UpdateGroupMemberNameResponse, err error) {
groupId := req.Id
personId := req.PersonId
memberName := req.MemberName
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err := s.UpdateMemberName(ctx, group, person, memberName); err != nil {
return nil, err
}
return res, nil
}
//updateGroupMemberName 更新群成员昵称
func (s *Service) updateGroupMemberName(groupId int64, memberId, memberName string) error {
err := s.dao.UpdateGroupMemberName(groupId, memberId, memberName)
if err != nil {
return err
}
return nil
}
func (s *Service) UpdateMemberName(ctx context.Context, group *biz.GroupInfo, person *biz.GroupMember, memberName string) error {
groupId := group.GroupId
personId := person.GroupMemberId
if err := s.updateGroupMemberName(groupId, personId, memberName); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,159 @@
package service
import (
"context"
xerror "gitlab.33.cn/chat/dtalk/pkg/error"
"gitlab.33.cn/chat/dtalk/service/group/model/biz"
"gitlab.33.cn/chat/dtalk/service/group/model/db"
"gitlab.33.cn/chat/dtalk/service/group/model/types"
)
// UpdateMembersMuteTimeSvc 设置群成员禁言时间
func (s *Service) UpdateMembersMuteTimeSvc(ctx context.Context, req *types.UpdateGroupMemberMuteTimeRequest) (res *types.UpdateGroupMemberMuteTimeResponse, err error) {
groupId := req.Id
memberIds := req.MemberIds
personId := req.PersonId
muteTime := req.MuteTime
//nowTime := s.getNowTime()
//log := s.GetLogWithTrace(ctx)
var members []*biz.GroupMember
//if muteTime != biz.MuteMaximum {
// if muteTime > (24 * 60 * 60 * 1000) {
// return nil, xerror.NewError(xerror.ParamsError)
// }
// if muteTime != 0 {
// muteTime += nowTime
// }
//}
group, err := s.GetGroupInfoByGroupId(ctx, groupId)
if err != nil {
return nil, err
}
person, err := s.GetPersonByMemberIdAndGroupId(ctx, personId, groupId)
if err != nil {
return nil, err
}
if err = person.IsAdmin(); err != nil {
return nil, err
}
// 过滤
for _, memberId := range memberIds {
member, err := s.GetMemberByMemberIdAndGroupId(ctx, memberId, groupId)
if err != nil {
return nil, err
}
if err := member.IsAdmin(); err == nil {
return nil, xerror.NewError(xerror.GroupMutePermission)
}
members = append(members, member)
}
members, err = s.UpdateMembersMuteTime(ctx, group, members, muteTime)
if err != nil {
return nil, err
}
//groupMemberMute := make([]*db.GroupMemberMute, len(memberIds), len(memberIds))
//for i, memberId := range memberIds {
// groupMemberMute[i] = &db.GroupMemberMute{
// GroupId: groupId,
// GroupMemberId: memberId,
// GroupMemberMuteTime: muteTime,
// GroupMemberMuteUpdateTime: nowTime,
// }
//}
//if err = s.execSetMemberMuteTimes(ctx, groupMemberMute); err != nil {
// return nil, err
//}
//
//// 发送给 pusher
//if err = s.PusherSignalMemberMuteTime(ctx, groupId, memberIds, muteTime); err != nil {
// log.Error().Err(err).Msg("UpdateMembersMuteTimeSvc pusher")
//}
//
//// 发送给 alert
//if muteTime != 0 {
// if err = s.NoticeMsgUpdateGroupMemberMutedTime(ctx, groupId, personId, memberIds); err != nil {
// log.Error().Err(err).Msg("UpdateMembersMuteTimeSvc alert")
// }
//}
res = &types.UpdateGroupMemberMuteTimeResponse{
Members: make([]*types.GroupMember, 0, len(members)),
}
for _, member := range members {
res.Members = append(res.Members, member.ToTypes())
}
return res, nil
}
// execSetMemberMuteTimes 执行设置群员禁言
func (s *Service) execSetMemberMuteTimes(ctx context.Context, memberMutes []*db.GroupMemberMute) error {
tx, err := s.dao.NewTx()
if err != nil {
return err
}
defer tx.RollBack()
if err = s.dao.UpdateGroupMemberMuteTimes(ctx, tx, memberMutes); err != nil {
return err
}
if err = tx.Commit(); err != nil {
return err
}
return nil
}
func (s *Service) UpdateMembersMuteTime(ctx context.Context, group *biz.GroupInfo, members []*biz.GroupMember, muteTime int64) ([]*biz.GroupMember, error) {
nowTime := s.getNowTime()
groupId := group.GroupId
log := s.GetLogWithTrace(ctx)
var memberIds []string
if muteTime != biz.MuteMaximum {
if muteTime > (24 * 60 * 60 * 1000) {
return nil, xerror.NewError(xerror.ParamsError)
}
if muteTime != 0 {
muteTime += nowTime
}
}
groupMemberMutes := make([]*db.GroupMemberMute, 0, len(members))
for _, member := range members {
groupMemberMutes = append(groupMemberMutes, &db.GroupMemberMute{
GroupId: groupId,
GroupMemberId: member.GroupMemberId,
GroupMemberMuteTime: muteTime,
})
memberIds = append(memberIds, member.GroupMemberId)
member.GroupMemberMuteTime = muteTime
}
if err := s.execSetMemberMuteTimes(ctx, groupMemberMutes); err != nil {
return nil, err
}
// 发送给 pusher
if err := s.PusherSignalMemberMuteTime(ctx, groupId, memberIds, muteTime); err != nil {
log.Error().Err(err).Msg("UpdateMembersMuteTimeSvc pusher")
}
// 发送给 alert
if muteTime != 0 {
if err := s.NoticeMsgUpdateGroupMemberMutedTime(ctx, groupId, s.GetOpe(ctx), memberIds); err != nil {
log.Error().Err(err).Msg("UpdateMembersMuteTimeSvc alert")
}
}
return members, nil
}