Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ 添加水群时长统计 #913

Merged
merged 12 commits into from
Jun 11, 2024
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,16 @@ zerobot [-h] [-m] [-n nickname] [-t token] [-u url] [-g url] [-p prefix] [-d|w]

- [x] 设置温度[正整数]

</details>
<details>
<summary>聊天时长统计</summary>

`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/chatcount"`

- [x] 查询水群@xxx

- [x] 查看水群排名

</details>
<details>
<summary>睡眠管理</summary>
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import (

_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chat" // 基础词库

_ "github.com/FloatTech/ZeroBot-Plugin/plugin/chatcount" // 聊天时长统计

_ "github.com/FloatTech/ZeroBot-Plugin/plugin/sleepmanage" // 统计睡眠时间

_ "github.com/FloatTech/ZeroBot-Plugin/plugin/atri" // ATRI词库
Expand Down
61 changes: 61 additions & 0 deletions plugin/chatcount/chatcount.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Package chatcount 聊天时长统计
package chatcount

import (
"fmt"
"strconv"
"strings"

zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"

ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
)

const (
rankSize = 15
)

func init() {
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "聊天时长统计",
Help: "- 查询水群@xxx\n- 查看水群排名",
PrivateDataFolder: "chatcount",
})
go func() {
ctdb = initialize(engine.DataFolder() + "chatcount.db")
fumiama marked this conversation as resolved.
Show resolved Hide resolved
}()
engine.OnMessage(zero.OnlyGroup).SetBlock(false).
Handle(func(ctx *zero.Ctx) {
todayTime, remindFlag := ctdb.updateChatTime(ctx.Event.GroupID, ctx.Event.UserID)
fumiama marked this conversation as resolved.
Show resolved Hide resolved
if remindFlag {
ctx.SendChain(message.At(ctx.Event.UserID), message.Text(fmt.Sprintf("BOT提醒:你今天已经水群%d分钟了!", todayTime)))
}
})

engine.OnPrefix(`查询水群`, zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
fumiama marked this conversation as resolved.
Show resolved Hide resolved
name := ctx.NickName()
todayTime, totalTime := ctdb.getChatTime(ctx.Event.GroupID, ctx.Event.UserID)
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(fmt.Sprintf("%s今天水了%d分钟,总计%d分钟。", name, todayTime, totalTime)))
})
engine.OnFullMatch("查看水群排名", zero.OnlyGroup).Limit(ctxext.LimitByGroup).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
text := strings.Builder{}
text.WriteString("今日水群排行榜:\n")
chatTimeList := ctdb.getChatRank(ctx.Event.GroupID)
for i := 0; i < len(chatTimeList) && i < rankSize; i++ {
text.WriteString("第")
text.WriteString(strconv.Itoa(i + 1))
text.WriteString("名:")
text.WriteString(ctx.CardOrNickName(chatTimeList[i].UserID))
text.WriteString(" - ")
text.WriteString(strconv.FormatInt(chatTimeList[i].TodayTime/60, 10))
text.WriteString("分钟\n")
}
ctx.SendChain(message.Text(text.String()))
})

}
143 changes: 143 additions & 0 deletions plugin/chatcount/model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package chatcount

import (
"os"
"sync"
"time"

"github.com/jinzhu/gorm"
)

const (
chatInterval = 300
)

var (
// ctdb 聊天时长数据库全局变量
ctdb *chattimedb
// levelArray 水群提醒时间提醒段,单位分钟
levelArray = [...]int{15, 30, 60, 120, 240}
// chatmu 读写添加锁
chatmu sync.Mutex
fumiama marked this conversation as resolved.
Show resolved Hide resolved
)

// chattimedb 聊天时长数据库结构体
type chattimedb gorm.DB

// initialize 初始化
func initialize(dbpath string) *chattimedb {
var err error
if _, err = os.Stat(dbpath); err != nil || os.IsNotExist(err) {
// 生成文件
f, err := os.Create(dbpath)
if err != nil {
return nil
}
defer f.Close()
}
gdb, err := gorm.Open("sqlite3", dbpath)
if err != nil {
panic(err)
}
gdb.AutoMigrate(&ChatTime{})
return (*chattimedb)(gdb)
}

// Close 关闭
func (ctdb *chattimedb) Close() error {
db := (*gorm.DB)(ctdb)
return db.Close()
}

// ChatTime 聊天时长,时间的单位都是秒
type ChatTime struct {
fumiama marked this conversation as resolved.
Show resolved Hide resolved
ID uint `gorm:"primary_key"`
GroupID int64 `gorm:"column:group_id"`
UserID int64 `gorm:"column:user_id"`
LastTime time.Time `gorm:"column:last_time"`
TodayTime int64 `gorm:"column:today_time;default:0"`
TotalTime int64 `gorm:"column:total_time;default:0"`
}

// TableName 表名
func (ChatTime) TableName() string {
return "chat_time"
}

// updateChatTime 更新发言时间,todayTime的单位是分钟
func (ctdb *chattimedb) updateChatTime(gid, uid int64) (todayTime int64, remindFlag bool) {
chatmu.Lock()
defer chatmu.Unlock()
db := (*gorm.DB)(ctdb)
now := time.Now()
st := ChatTime{
GroupID: gid,
UserID: uid,
LastTime: now,
}
if err := db.Model(&ChatTime{}).Where("group_id = ? and user_id = ?", gid, uid).First(&st).Error; err != nil {
fumiama marked this conversation as resolved.
Show resolved Hide resolved
if gorm.IsRecordNotFoundError(err) {
db.Model(&ChatTime{}).Create(&st)
}
} else {
// 如果不是同一天,把todayTime重置
if st.LastTime.YearDay() != now.YearDay() {
db.Model(&ChatTime{}).Where("group_id = ? and user_id = ?", gid, uid).Update(
map[string]any{
"last_time": now,
"today_time": 0,
})
} else {
userChatTime := int64(now.Sub(st.LastTime).Seconds())
// 当聊天时间间隔很大的话,则不计入时长
if userChatTime < chatInterval {
db.Model(&ChatTime{}).Where("group_id = ? and user_id = ?", gid, uid).Update(
map[string]any{
"last_time": now,
"today_time": st.TodayTime + userChatTime,
"total_time": st.TotalTime + userChatTime,
})
todayTime = (st.TodayTime + userChatTime) / 60
remindFlag = getLevel(int(st.TodayTime+userChatTime)/60) > getLevel(int(st.TodayTime/60))
} else {
db.Model(&ChatTime{}).Where("group_id = ? and user_id = ?", gid, uid).Update(
map[string]any{
"last_time": now,
})
}

}
}
return
}

// getChatTime 获得用户聊天时长,todayTime,totalTime的单位是分钟
func (ctdb *chattimedb) getChatTime(gid, uid int64) (todayTime int64, totalTime int64) {
chatmu.Lock()
defer chatmu.Unlock()
db := (*gorm.DB)(ctdb)
st := ChatTime{}
db.Model(&ChatTime{}).Where("group_id = ? and user_id = ?", gid, uid).First(&st)
fumiama marked this conversation as resolved.
Show resolved Hide resolved
todayTime = st.TodayTime / 60
totalTime = st.TotalTime / 60
return
}

// getChatRank 获得水群排名
func (ctdb *chattimedb) getChatRank(gid int64) (chatTimeList []ChatTime) {
chatmu.Lock()
defer chatmu.Unlock()
db := (*gorm.DB)(ctdb)
db.Model(&ChatTime{}).Where("group_id = ?", gid).Order("today_time DESC").Find(&chatTimeList)
return
}

// getLevel 用时长判断等级
func getLevel(t int) int {
fumiama marked this conversation as resolved.
Show resolved Hide resolved
for i := len(levelArray) - 1; i >= 0; i-- {
if t >= levelArray[i] {
return i + 1
}
}
return 0
}
Loading