🆕 新增清理不活跃成员功能 #49
@ -20,6 +20,7 @@ type Friend struct {
|
|||||||
EnableWelcome bool `json:"enableWelcome" gorm:"type:tinyint(1) default 0 not null"` // 是否启用迎新
|
EnableWelcome bool `json:"enableWelcome" gorm:"type:tinyint(1) default 0 not null"` // 是否启用迎新
|
||||||
EnableSummary bool `json:"enableSummary" gorm:"type:tinyint(1) default 0 not null"` // 是否启用总结
|
EnableSummary bool `json:"enableSummary" gorm:"type:tinyint(1) default 0 not null"` // 是否启用总结
|
||||||
EnableNews bool `json:"enableNews" gorm:"type:tinyint(1) default 0 not null"` // 是否启用新闻
|
EnableNews bool `json:"enableNews" gorm:"type:tinyint(1) default 0 not null"` // 是否启用新闻
|
||||||
|
ClearMember int `json:"clearMember"` // 清理成员配置(多少天未活跃的)
|
||||||
IsOk bool `json:"isOk" gorm:"type:tinyint(1) default 0 not null"` // 是否正常
|
IsOk bool `json:"isOk" gorm:"type:tinyint(1) default 0 not null"` // 是否正常
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +77,15 @@ func GetAllEnableNews() (records []entity.Friend, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAllEnableClearGroup
|
||||||
|
// @description: 获取所有需要清理成员的群组
|
||||||
|
// @return records
|
||||||
|
// @return err
|
||||||
|
func GetAllEnableClearGroup() (records []entity.Friend, err error) {
|
||||||
|
err = client.MySQL.Where("clear_members != 0").Where("is_ok IS TRUE").Find(&records).Error
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// CheckIsEnableCommand
|
// CheckIsEnableCommand
|
||||||
// @description: 检查用户是否启用了指令
|
// @description: 检查用户是否启用了指令
|
||||||
// @param userId
|
// @param userId
|
||||||
|
68
tasks/cleargroupuser/cleargroupuser.go
Normal file
68
tasks/cleargroupuser/cleargroupuser.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package cleargroupuser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go-wechat/client"
|
||||||
|
"go-wechat/entity"
|
||||||
|
"go-wechat/service"
|
||||||
|
"go-wechat/utils"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ClearGroupUser
|
||||||
|
// @description: 清理群成员
|
||||||
|
func ClearGroupUser() {
|
||||||
|
groups, err := service.GetAllEnableNews()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("获取启用了聊天排行榜的群组失败, 错误信息: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, group := range groups {
|
||||||
|
// 获取需要清理的群成员Id
|
||||||
|
members := getNeedDeleteMembers(group.Wxid, group.ClearMember)
|
||||||
|
memberCount := len(members)
|
||||||
|
log.Printf("群[%s(%s)]需要清理的成员数量: %d", group.Nickname, group.Wxid, memberCount)
|
||||||
|
if memberCount < 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var memberMap = make(map[string]string)
|
||||||
|
var deleteIds = make([]string, 0)
|
||||||
|
for _, member := range members {
|
||||||
|
deleteIds = append(deleteIds, member.Wxid)
|
||||||
|
// 昵称为空,取id后4位
|
||||||
|
if member.Nickname == "" {
|
||||||
|
member.Nickname = "无名氏_" + member.Wxid[len(member.Wxid)-4:]
|
||||||
|
}
|
||||||
|
memberMap[member.Nickname] = member.LastActive.Format("2006-01-02 15:04:05")
|
||||||
|
}
|
||||||
|
// 调用接口
|
||||||
|
utils.DeleteGroupMember(group.Wxid, strings.Join(deleteIds, ","), 0)
|
||||||
|
// 发送通知到群里
|
||||||
|
ms := make([]string, 0)
|
||||||
|
for k, v := range memberMap {
|
||||||
|
ms = append(ms, fmt.Sprintf("%s: %s", k, v))
|
||||||
|
}
|
||||||
|
msg := fmt.Sprintf("#清理群成员#\n\n很遗憾地通知各位,就在刚刚,有%d名群友引活跃度不够暂时离开了我们,希望还健在的群友引以为戒、保持活跃!\n\n活跃信息: \n%s",
|
||||||
|
memberCount, strings.Join(ms, "\n"))
|
||||||
|
utils.SendMessage(group.Wxid, "", msg, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// getNeedDeleteMembers
|
||||||
|
// @description: 获取需要删除的群成员
|
||||||
|
// @param groupId 群Id
|
||||||
|
// @param days 需要清理的未活跃的天数
|
||||||
|
// @return members
|
||||||
|
func getNeedDeleteMembers(groupId string, days int) (members []entity.GroupUser) {
|
||||||
|
err := client.MySQL.Model(&entity.GroupUser{}).Where("group_id = ?", groupId).
|
||||||
|
Where("is_member IS TRUE").
|
||||||
|
Where("DATEDIFF( NOW(), last_active ) >= ?", days).
|
||||||
|
Order("last_active DESC").
|
||||||
|
Find(&members).Error
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("获取需要清理的群成员失败, 错误信息: %v", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
@ -75,6 +75,7 @@ func Sync() {
|
|||||||
EnableSummary: config.Conf.System.DefaultRule.Summary,
|
EnableSummary: config.Conf.System.DefaultRule.Summary,
|
||||||
EnableWelcome: config.Conf.System.DefaultRule.Welcome,
|
EnableWelcome: config.Conf.System.DefaultRule.Welcome,
|
||||||
EnableNews: config.Conf.System.DefaultRule.News,
|
EnableNews: config.Conf.System.DefaultRule.News,
|
||||||
|
ClearMember: 0,
|
||||||
LastActive: time.Now().Local(),
|
LastActive: time.Now().Local(),
|
||||||
}).Error
|
}).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3,6 +3,7 @@ package tasks
|
|||||||
import (
|
import (
|
||||||
"github.com/go-co-op/gocron"
|
"github.com/go-co-op/gocron"
|
||||||
"go-wechat/config"
|
"go-wechat/config"
|
||||||
|
"go-wechat/tasks/cleargroupuser"
|
||||||
"go-wechat/tasks/friends"
|
"go-wechat/tasks/friends"
|
||||||
"go-wechat/tasks/news"
|
"go-wechat/tasks/news"
|
||||||
"go-wechat/tasks/summary"
|
"go-wechat/tasks/summary"
|
||||||
@ -56,6 +57,9 @@ func InitTasks() {
|
|||||||
_, _ = s.Cron(config.Conf.Task.News.Cron).Do(news.DailyNews)
|
_, _ = s.Cron(config.Conf.Task.News.Cron).Do(news.DailyNews)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 每天0点检查一次处理清理群成员
|
||||||
|
_, _ = s.Cron("0 0 * * *").Do(cleargroupuser.ClearGroupUser)
|
||||||
|
|
||||||
// 开启定时任务
|
// 开启定时任务
|
||||||
s.StartAsync()
|
s.StartAsync()
|
||||||
log.Println("定时任务初始化成功")
|
log.Println("定时任务初始化成功")
|
||||||
|
@ -32,7 +32,7 @@ func getRankData(groupId, date string) (rank []rankUser, err error) {
|
|||||||
case "week":
|
case "week":
|
||||||
tx.Where("YEARWEEK(date_format(tm.create_at, '%Y-%m-%d')) = YEARWEEK(now()) - 1")
|
tx.Where("YEARWEEK(date_format(tm.create_at, '%Y-%m-%d')) = YEARWEEK(now()) - 1")
|
||||||
case "month":
|
case "month":
|
||||||
tx.Where("PERIOD_DIFF(date_format(now(), '%Y%m'), date_format(create_at, '%Y%m')) = 1")
|
tx.Where("PERIOD_DIFF(date_format(now(), '%Y%m'), date_format(tm.create_at, '%Y%m')) = 1")
|
||||||
case "year":
|
case "year":
|
||||||
tx.Where("YEAR(tm.create_at) = YEAR(NOW()) - 1")
|
tx.Where("YEAR(tm.create_at) = YEAR(NOW()) - 1")
|
||||||
}
|
}
|
||||||
|
@ -121,3 +121,34 @@ func SendEmotion(toId, emotionHash string, retryCount int) {
|
|||||||
}
|
}
|
||||||
log.Printf("发送表情包消息结果: %s", resp.String())
|
log.Printf("发送表情包消息结果: %s", resp.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteGroupMember
|
||||||
|
// @description: 删除群成员
|
||||||
|
// @param chatRoomId 群Id
|
||||||
|
// @param memberIds 成员id,用','分隔
|
||||||
|
func DeleteGroupMember(chatRoomId, memberIds string, retryCount int) {
|
||||||
|
if retryCount > 5 {
|
||||||
|
log.Printf("重试五次失败,停止发送")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组装参数
|
||||||
|
param := map[string]any{
|
||||||
|
"chatRoomId": chatRoomId, // 群Id
|
||||||
|
"memberIds": memberIds, // 成员id
|
||||||
|
}
|
||||||
|
pbs, _ := json.Marshal(param)
|
||||||
|
|
||||||
|
res := resty.New()
|
||||||
|
resp, err := res.R().
|
||||||
|
SetHeader("Content-Type", "application/json;chartset=utf-8").
|
||||||
|
SetBody(string(pbs)).
|
||||||
|
Post(config.Conf.Wechat.GetURL("/api/delMemberFromChatRoom"))
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("删除群成员失败: %s", err.Error())
|
||||||
|
// 休眠五秒后重新发送
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
SendImage(chatRoomId, memberIds, retryCount+1)
|
||||||
|
}
|
||||||
|
log.Printf("删除群成员结果: %s", resp.String())
|
||||||
|
}
|
||||||
|
@ -50,6 +50,9 @@
|
|||||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||||
指令
|
指令
|
||||||
</th>
|
</th>
|
||||||
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||||
|
末位淘汰(天)
|
||||||
|
</th>
|
||||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||||
操作
|
操作
|
||||||
</th>
|
</th>
|
||||||
@ -107,6 +110,9 @@
|
|||||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||||
{{ template "command" . }}
|
{{ template "command" . }}
|
||||||
</td>
|
</td>
|
||||||
|
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||||
|
{{ .ClearMember }}
|
||||||
|
</td>
|
||||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||||
<button class="btn btn-link" onclick="getGroupUsers({{.Wxid}}, {{.Nickname}})">成员</button>
|
<button class="btn btn-link" onclick="getGroupUsers({{.Wxid}}, {{.Nickname}})">成员</button>
|
||||||
</td>
|
</td>
|
||||||
|
@ -20,6 +20,7 @@ type FriendItem struct {
|
|||||||
EnableCommand bool // 是否启用指令
|
EnableCommand bool // 是否启用指令
|
||||||
EnableSummary bool // 是否启用总结
|
EnableSummary bool // 是否启用总结
|
||||||
EnableNews bool // 是否启用新闻
|
EnableNews bool // 是否启用新闻
|
||||||
|
ClearMember int // 清理成员配置(多少天未活跃的)
|
||||||
IsOk bool // 是否还在通讯库(群聊是要还在群里也算)
|
IsOk bool // 是否还在通讯库(群聊是要还在群里也算)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user