mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 05:30:07 +08:00
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
447 lines
14 KiB
Go
447 lines
14 KiB
Go
// Package qqwife 娶群友 基于“翻牌”和江林大佬的“群老婆”插件魔改作品,文案采用了Hana的zbp娶群友文案
|
||
package qqwife
|
||
|
||
import (
|
||
"math/rand"
|
||
"sort"
|
||
"strconv"
|
||
"strings"
|
||
"sync"
|
||
"time"
|
||
|
||
"github.com/FloatTech/floatbox/math"
|
||
ctrl "github.com/FloatTech/zbpctrl"
|
||
control "github.com/FloatTech/zbputils/control"
|
||
"github.com/FloatTech/zbputils/ctxext"
|
||
zero "github.com/wdvxdr1123/ZeroBot"
|
||
"github.com/wdvxdr1123/ZeroBot/message"
|
||
|
||
// 反并发
|
||
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||
// 数据库
|
||
sql "github.com/FloatTech/sqlite"
|
||
// 画图
|
||
"github.com/Coloured-glaze/gg"
|
||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||
"github.com/FloatTech/floatbox/file"
|
||
"github.com/FloatTech/floatbox/img/writer"
|
||
"github.com/FloatTech/zbputils/img/text"
|
||
// 货币系统
|
||
)
|
||
|
||
type 婚姻登记 struct {
|
||
db *sql.Sqlite
|
||
sync.RWMutex
|
||
}
|
||
|
||
// 群设置
|
||
type updateinfo struct {
|
||
GID int64
|
||
Updatetime string // 登记时间
|
||
CanMatch int // 嫁婚开关
|
||
CanNtr int // Ntr开关
|
||
CDtime float64 // CD时间
|
||
}
|
||
|
||
// 结婚证信息
|
||
type userinfo struct {
|
||
User int64 // 用户身份证
|
||
Target int64 // 对象身份证号
|
||
Username string // 户主名称
|
||
Targetname string // 对象名称
|
||
Updatetime string // 登记时间
|
||
|
||
}
|
||
|
||
var (
|
||
民政局 = &婚姻登记{
|
||
db: &sql.Sqlite{},
|
||
}
|
||
engine = control.Register("qqwife", &ctrl.Options[*zero.Ctx]{
|
||
DisableOnDefault: false,
|
||
Brief: "一群一天一夫一妻制群老婆",
|
||
Help: "- 娶群友\n- 群老婆列表\n- [允许|禁止]自由恋爱\n- [允许|禁止]牛头人\n- 设置CD为xx小时 →(默认12小时)\n- 重置花名册\n- 重置所有花名册(用于清除所有群数据及其设置)\n- 查好感度[对方Q号|@对方QQ]\n- 好感度列表\n" +
|
||
"--------------------------------\n以下指令存在CD,不跨天刷新,前两个受指令开关\n--------------------------------\n" +
|
||
"- (娶|嫁)@对方QQ\n自由选择对象, 自由恋爱(好感度越高成功率越高,保底30%概率)\n" +
|
||
"- 当[对方Q号|@对方QQ]的小三\n我和你才是真爱, 为了你我愿意付出一切(好感度越高成功率越高,保底10%概率)\n" +
|
||
"- 闹离婚\n你谁啊, 给我滚(好感度越高成功率越低)\n" +
|
||
"- 买礼物给[对方Q号|@对方QQ]\n使用小熊饼干获取好感度\n" +
|
||
"- 做媒 @攻方QQ @受方QQ\n身为管理, 群友的xing福是要搭把手的(攻受双方好感度越高成功率越高,保底30%概率)\n" +
|
||
"--------------------------------\n好感度规则\n--------------------------------\n" +
|
||
"\"娶群友\"指令好感度随机增加1~5。\n\"A牛B的C\"会导致C恨A, 好感度-5;\nB为了报复A, 好感度+5(什么柜子play)\nA为BC做媒,成功B、C对A好感度+1反之-1\n做媒成功BC好感度+1" +
|
||
"Tips: 群老婆列表过0点刷新",
|
||
PrivateDataFolder: "qqwife",
|
||
}).ApplySingle(single.New(
|
||
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
|
||
single.WithPostFn[int64](func(ctx *zero.Ctx) {
|
||
ctx.Send(
|
||
message.ReplyWithMessage(ctx.Event.MessageID,
|
||
message.Text("别着急,民政局门口排长队了!"),
|
||
),
|
||
)
|
||
}),
|
||
))
|
||
getdb = fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||
民政局.db.DBPath = engine.DataFolder() + "结婚登记表.db"
|
||
err := 民政局.db.Open(time.Hour * 24)
|
||
if err == nil {
|
||
// 创建群配置表
|
||
err = 民政局.db.Create("updateinfo", &updateinfo{})
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return false
|
||
}
|
||
// 创建CD表
|
||
err = 民政局.db.Create("cdsheet", &cdsheet{})
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return false
|
||
}
|
||
// 创建好感度表
|
||
err = 民政局.db.Create("favorability", &favorability{})
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return false
|
||
}
|
||
return true
|
||
}
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return false
|
||
})
|
||
)
|
||
|
||
func init() {
|
||
engine.OnFullMatch("娶群友", zero.OnlyGroup, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
|
||
Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
err := 民政局.开门时间(gid)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return
|
||
}
|
||
uid := ctx.Event.UserID
|
||
userInfo, _ := 民政局.查户口(gid, uid)
|
||
switch {
|
||
case userInfo != (userinfo{}) && (userInfo.Target == 0 || userInfo.User == 0): // 如果是单身贵族
|
||
ctx.SendChain(message.Text("今天你是单身贵族噢"))
|
||
return
|
||
case userInfo.User == uid: // 娶过别人
|
||
ctx.SendChain(
|
||
message.At(uid),
|
||
message.Text("\n今天你在", userInfo.Updatetime, "娶了群友"),
|
||
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(userInfo.Target, 10)+"&s=640").Add("cache", 0),
|
||
message.Text(
|
||
"\n",
|
||
"[", userInfo.Targetname, "]",
|
||
"(", userInfo.Target, ")哒",
|
||
),
|
||
)
|
||
return
|
||
case userInfo.Target == uid: // 嫁给别人
|
||
ctx.SendChain(
|
||
message.At(uid),
|
||
message.Text("\n今天你在", userInfo.Updatetime, "被群友"),
|
||
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(userInfo.User, 10)+"&s=640").Add("cache", 0),
|
||
message.Text(
|
||
"\n",
|
||
"[", userInfo.Username, "]",
|
||
"(", userInfo.User, ")娶了",
|
||
),
|
||
)
|
||
return
|
||
}
|
||
// 无缓存获取群员列表
|
||
temp := ctx.GetThisGroupMemberListNoCache().Array()
|
||
sort.SliceStable(temp, func(i, j int) bool {
|
||
return temp[i].Get("last_sent_time").Int() < temp[j].Get("last_sent_time").Int()
|
||
})
|
||
temp = temp[math.Max(0, len(temp)-30):]
|
||
// 将已经娶过的人剔除
|
||
qqgrouplist := make([]int64, 0, len(temp))
|
||
for k := 0; k < len(temp); k++ {
|
||
usr := temp[k].Get("user_id").Int()
|
||
usrInfo, _ := 民政局.查户口(gid, usr)
|
||
if usrInfo != (userinfo{}) {
|
||
continue
|
||
}
|
||
qqgrouplist = append(qqgrouplist, usr)
|
||
}
|
||
// 没有人(只剩自己)的时候
|
||
if len(qqgrouplist) == 1 {
|
||
ctx.SendChain(message.Text("~群里没有ta人是单身了哦 明天再试试叭"))
|
||
return
|
||
}
|
||
// 随机抽娶
|
||
fiancee := qqgrouplist[rand.Intn(len(qqgrouplist))]
|
||
if fiancee == uid { // 如果是自己
|
||
switch rand.Intn(10) {
|
||
case 1:
|
||
err := 民政局.登记(gid, uid, 0, "", "")
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Text("今日获得成就:单身贵族"))
|
||
default:
|
||
ctx.SendChain(message.Text("呜...没娶到,你可以再尝试一次"))
|
||
return
|
||
}
|
||
}
|
||
// 去民政局办证
|
||
err = 民政局.登记(gid, uid, fiancee, ctx.CardOrNickName(uid), ctx.CardOrNickName(fiancee))
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return
|
||
}
|
||
favor, err := 民政局.更新好感度(uid, fiancee, 1+rand.Intn(5))
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
}
|
||
// 请大家吃席
|
||
ctx.SendChain(
|
||
message.At(uid),
|
||
message.Text("今天你的群老婆是"),
|
||
message.Image("http://q4.qlogo.cn/g?b=qq&nk="+strconv.FormatInt(fiancee, 10)+"&s=640").Add("cache", 0),
|
||
message.Text(
|
||
"\n",
|
||
"[", ctx.CardOrNickName(fiancee), "]",
|
||
"(", fiancee, ")哒\n当前你们好感度为", favor,
|
||
),
|
||
)
|
||
})
|
||
engine.OnFullMatch("群老婆列表", zero.OnlyGroup, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
|
||
Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
err := 民政局.开门时间(gid)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return
|
||
}
|
||
list, err := 民政局.花名册(gid)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return
|
||
}
|
||
number := len(list)
|
||
if number <= 0 {
|
||
ctx.SendChain(message.Text("今天还没有人结婚哦"))
|
||
return
|
||
}
|
||
/***********设置图片的大小和底色***********/
|
||
fontSize := 50.0
|
||
if number < 10 {
|
||
number = 10
|
||
}
|
||
canvas := gg.NewContext(1500, int(250+fontSize*float64(number)))
|
||
canvas.SetRGB(1, 1, 1) // 白色
|
||
canvas.Clear()
|
||
/***********下载字体,可以注销掉***********/
|
||
_, err = file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[qqwife]ERROR: ", err))
|
||
}
|
||
/***********设置字体颜色为黑色***********/
|
||
canvas.SetRGB(0, 0, 0)
|
||
/***********设置字体大小,并获取字体高度用来定位***********/
|
||
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize*2); err != nil {
|
||
ctx.SendChain(message.Text("[qqwife]ERROR: ", err))
|
||
return
|
||
}
|
||
sl, h := canvas.MeasureString("群老婆列表")
|
||
/***********绘制标题***********/
|
||
canvas.DrawString("群老婆列表", (1500-sl)/2, 160-h) // 放置在中间位置
|
||
canvas.DrawString("————————————————————", 0, 250-h)
|
||
/***********设置字体大小,并获取字体高度用来定位***********/
|
||
if err = canvas.LoadFontFace(text.BoldFontFile, fontSize); err != nil {
|
||
ctx.SendChain(message.Text("[qqwife]ERROR: ", err))
|
||
return
|
||
}
|
||
_, h = canvas.MeasureString("焯")
|
||
for i, info := range list {
|
||
canvas.DrawString(slicename(info[0], canvas), 0, float64(260+50*i)-h)
|
||
canvas.DrawString("("+info[1]+")", 350, float64(260+50*i)-h)
|
||
canvas.DrawString("←→", 700, float64(260+50*i)-h)
|
||
canvas.DrawString(slicename(info[2], canvas), 800, float64(260+50*i)-h)
|
||
canvas.DrawString("("+info[3]+")", 1150, float64(260+50*i)-h)
|
||
}
|
||
data, cl := writer.ToBytes(canvas.Image())
|
||
ctx.SendChain(message.ImageBytes(data))
|
||
cl()
|
||
})
|
||
engine.OnRegex(`^重置(所有|本群|/d+)?花名册$`, zero.SuperUserPermission, getdb).SetBlock(true).Limit(ctxext.LimitByUser).
|
||
Handle(func(ctx *zero.Ctx) {
|
||
var err error
|
||
switch ctx.State["regex_matched"].([]string)[1] {
|
||
case "所有":
|
||
err = 民政局.清理花名册()
|
||
case "本群", "":
|
||
if ctx.Event.GroupID == 0 {
|
||
ctx.SendChain(message.Text("该功能只能在群组使用或者指定群组"))
|
||
return
|
||
}
|
||
err = 民政局.清理花名册("group" + strconv.FormatInt(ctx.Event.GroupID, 10))
|
||
default:
|
||
cmd := ctx.State["regex_matched"].([]string)[1]
|
||
gid, _ := strconv.ParseInt(cmd, 10, 64) // 判断是否为群号
|
||
if gid == 0 {
|
||
ctx.SendChain(message.Text("请输入正确的群号"))
|
||
return
|
||
}
|
||
err = 民政局.清理花名册("group" + cmd)
|
||
}
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR]:", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Text("重置成功"))
|
||
})
|
||
}
|
||
|
||
func (sql *婚姻登记) 查看设置(gid int64) (dbinfo updateinfo, err error) {
|
||
sql.Lock()
|
||
defer sql.Unlock()
|
||
// 创建群表哥
|
||
err = sql.db.Create("updateinfo", &updateinfo{})
|
||
if err != nil {
|
||
return
|
||
}
|
||
if !sql.db.CanFind("updateinfo", "where gid is "+strconv.FormatInt(gid, 10)) {
|
||
// 没有记录
|
||
return updateinfo{
|
||
GID: gid,
|
||
CanMatch: 1,
|
||
CanNtr: 1,
|
||
CDtime: 12,
|
||
}, nil
|
||
}
|
||
_ = sql.db.Find("updateinfo", &dbinfo, "where gid is "+strconv.FormatInt(gid, 10))
|
||
return
|
||
}
|
||
|
||
func (sql *婚姻登记) 更新设置(dbinfo updateinfo) error {
|
||
sql.Lock()
|
||
defer sql.Unlock()
|
||
return sql.db.Insert("updateinfo", &dbinfo)
|
||
}
|
||
|
||
func (sql *婚姻登记) 开门时间(gid int64) error {
|
||
grouInfo, err := sql.查看设置(gid)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
sql.Lock()
|
||
defer sql.Unlock()
|
||
dbinfo := updateinfo{}
|
||
_ = sql.db.Find("updateinfo", &dbinfo, "where gid is "+strconv.FormatInt(gid, 10))
|
||
if time.Now().Format("2006/01/02") != dbinfo.Updatetime {
|
||
// 如果跨天了就删除
|
||
_ = sql.db.Drop("group" + strconv.FormatInt(gid, 10))
|
||
// 更新数据时间
|
||
grouInfo.GID = gid
|
||
grouInfo.Updatetime = time.Now().Format("2006/01/02")
|
||
return sql.db.Insert("updateinfo", &grouInfo)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (sql *婚姻登记) 查户口(gid, uid int64) (info userinfo, err error) {
|
||
sql.Lock()
|
||
defer sql.Unlock()
|
||
gidstr := "group" + strconv.FormatInt(gid, 10)
|
||
// 创建群表哥
|
||
err = sql.db.Create(gidstr, &userinfo{})
|
||
if err != nil {
|
||
return
|
||
}
|
||
uidstr := strconv.FormatInt(uid, 10)
|
||
err = sql.db.Find(gidstr, &info, "where user = "+uidstr)
|
||
if err != nil {
|
||
err = sql.db.Find(gidstr, &info, "where target = "+uidstr)
|
||
}
|
||
return
|
||
}
|
||
|
||
// 民政局登记数据
|
||
func (sql *婚姻登记) 登记(gid, uid, target int64, username, targetname string) error {
|
||
sql.Lock()
|
||
defer sql.Unlock()
|
||
gidstr := "group" + strconv.FormatInt(gid, 10)
|
||
uidinfo := userinfo{
|
||
User: uid,
|
||
Username: username,
|
||
Target: target,
|
||
Targetname: targetname,
|
||
Updatetime: time.Now().Format("15:04:05"),
|
||
}
|
||
return sql.db.Insert(gidstr, &uidinfo)
|
||
}
|
||
|
||
func (sql *婚姻登记) 花名册(gid int64) (list [][4]string, err error) {
|
||
sql.Lock()
|
||
defer sql.Unlock()
|
||
gidstr := "group" + strconv.FormatInt(gid, 10)
|
||
number, _ := sql.db.Count(gidstr)
|
||
if number <= 0 {
|
||
return
|
||
}
|
||
var info userinfo
|
||
err = sql.db.FindFor(gidstr, &info, "GROUP BY user", func() error {
|
||
if info.Target == 0 {
|
||
return nil
|
||
}
|
||
dbinfo := [4]string{
|
||
info.Username,
|
||
strconv.FormatInt(info.User, 10),
|
||
info.Targetname,
|
||
strconv.FormatInt(info.Target, 10),
|
||
}
|
||
list = append(list, dbinfo)
|
||
return nil
|
||
})
|
||
return
|
||
}
|
||
|
||
func slicename(name string, canvas *gg.Context) (resultname string) {
|
||
usermane := []rune(name) // 将每个字符单独放置
|
||
widthlen := 0
|
||
numberlen := 0
|
||
for i, v := range usermane {
|
||
width, _ := canvas.MeasureString(string(v)) // 获取单个字符的宽度
|
||
widthlen += int(width)
|
||
if widthlen > 350 {
|
||
break // 总宽度不能超过350
|
||
}
|
||
numberlen = i
|
||
}
|
||
if widthlen > 350 {
|
||
resultname = string(usermane[:numberlen-1]) + "......" // 名字切片
|
||
} else {
|
||
resultname = name
|
||
}
|
||
return
|
||
}
|
||
|
||
func (sql *婚姻登记) 清理花名册(gid ...string) error {
|
||
sql.Lock()
|
||
defer sql.Unlock()
|
||
switch gid {
|
||
case nil:
|
||
grouplist, err := sql.db.ListTables()
|
||
if err == nil {
|
||
for _, listName := range grouplist {
|
||
if listName == "favorability" {
|
||
continue
|
||
}
|
||
err = sql.db.Drop(listName)
|
||
}
|
||
}
|
||
return err
|
||
default:
|
||
err := sql.db.Drop(gid[0])
|
||
if err == nil {
|
||
_ = sql.db.Del("cdsheet", "where GroupID is "+strings.ReplaceAll(gid[0], "group", ""))
|
||
}
|
||
return err
|
||
}
|
||
}
|