扩增文心AI的功能,修复猜歌的权限问题 (#471)

This commit is contained in:
方柳煜 2022-10-24 23:36:28 +08:00 committed by GitHub
parent 21712c6299
commit d43ea7df1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 352 additions and 43 deletions

View File

@ -1137,21 +1137,45 @@ print("run[CQ:image,file="+j["img"]+"]")
</details>
<details>
<summary>百度文心AI画图</summary>
<summary>百度文心AI</summary>
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/wenxinAI"`
- 基于百度文心的免费AI画图插件(因为是免费的,图片质量你懂的)
基于百度文心API的一些功能
- key申请链接https://wenxin.baidu.com/moduleApi/key
- [x] 为[自己/本群/QQ号/群+群号]设置AI画图key [API Key] [Secret Key]
- 例“为10086设置AI画图key 123 456”“为群10010设置AI画图key 789 101”
key申请链接https://wenxin.baidu.com/moduleApi/key
- [x] 为[自己/本群/QQ号/群+群号]设置文心key [API Key] [Secret Key]
- [x] 为[自己/本群/QQ号/群+群号]设置画图key [API Key] [Secret Key]
“为10086设置画图key 123 456”“为群10010设置画图key 789 101”
文心key和画图key的API key 可以是相同的只是文心key日限为200画图日限为50以此作区别。
- [x] 文心作文 (x字的)[作文题目]
- [x] 文心提案 (x字的)[文案标题]
- [x] 文心摘要 (x字的)[文章内容]
- [x] 文心小说 (x字的)[小说上文]
- [x] 文心对联 [上联]
- [x] 文心问答 [问题]
- [x] 文心补全 [带“_”的填空题]
- [x] 文心自定义 [prompt]
- [x] [bot名称]画几张[图片描述]的[图片类型][图片尺寸]
- 指令示例:
指令示例:
- 文心作文 我的椛椛机器人
- 文心作文 300字的我的椛椛机器人
- 椛椛帮我画几张金凤凰背景绚烂高饱和古风仙境高清4K古风的油画方图

2
go.mod
View File

@ -4,7 +4,7 @@ go 1.19
require (
github.com/Coloured-glaze/gg v1.3.4
github.com/FloatTech/AnimeAPI v1.5.2-0.20221015060924-fe2f85a3cf45
github.com/FloatTech/AnimeAPI v1.5.2-0.20221023084913-bd1ff35e91ed
github.com/FloatTech/floatbox v0.0.0-20221011153549-68005767c531
github.com/FloatTech/sqlite v0.5.0
github.com/FloatTech/ttl v0.0.0-20220715042055-15612be72f5b

4
go.sum
View File

@ -2,8 +2,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/Coloured-glaze/gg v1.3.4 h1:l31zIF/HaVwkzjrj+A56RGQoSKyKuR1IWtIrqXGFStI=
github.com/Coloured-glaze/gg v1.3.4/go.mod h1:Ih5NLNNDHOy3RJbB0EPqGTreIzq/H02TGThIagh8HJg=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221015060924-fe2f85a3cf45 h1:XbNlD0irJELgdR304TvqmFrxdH7hsxA/Ah9xLHFP3eQ=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221015060924-fe2f85a3cf45/go.mod h1:RgcMDA1S7C81bq7HQjygMEEo+EXwAlsutvKMv7DafgY=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221023084913-bd1ff35e91ed h1:Jve+3koem2QAFWoB9c2qsDmhOdLQOAFfbfzG7y47tYQ=
github.com/FloatTech/AnimeAPI v1.5.2-0.20221023084913-bd1ff35e91ed/go.mod h1:RgcMDA1S7C81bq7HQjygMEEo+EXwAlsutvKMv7DafgY=
github.com/FloatTech/floatbox v0.0.0-20221011153549-68005767c531 h1:Z0yn6LFhEyC12hj+TBXc2P7/kWlCd/jlwv4JFndgpnw=
github.com/FloatTech/floatbox v0.0.0-20221011153549-68005767c531/go.mod h1:4tfIeB74L1RzhNp3nNjaTw8m3IEnc+q/k6k/MhL07ks=
github.com/FloatTech/sqlite v0.5.0 h1:U7J5Omc534PqmH6csfu+ypCo3DS8L91l5lTsxUu3b/U=

View File

@ -165,7 +165,7 @@ func init() { // 插件主体
ctx.SendChain(message.Text(serviceErr, "ERROR:\n", err))
}
})
engine.OnRegex(`^猜歌(开启|关闭)(歌单|歌词)自动下载`).SetBlock(true).
engine.OnRegex(`^猜歌(开启|关闭)(歌单|歌词)自动下载`, zero.SuperUserPermission).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
swtich := ctx.State["regex_matched"].([]string)[1]
option := ctx.State["regex_matched"].([]string)[1]

View File

@ -1,5 +1,5 @@
// Package ernie AI画图
package ernie
// Package wenxin 百度文心AI
package wenxin
import (
"errors"
@ -19,13 +19,17 @@ import (
// 数据库
sql "github.com/FloatTech/sqlite"
// 百度文心大模型
model "github.com/FloatTech/AnimeAPI/wenxinAI/erniemodle"
// 百度文心AI画图API
wenxin "github.com/FloatTech/AnimeAPI/wenxinAI/ernievilg"
)
const (
serviceName = "AIdraw"
serviceName = "wenxinvilg"
serviceErr = "[" + serviceName + "]ERROR:\n"
modelName = "wenxinmodel"
modelErr = "[" + modelName + "]ERROR:\n"
)
type keydb struct {
@ -46,24 +50,34 @@ type apikey struct {
}
var (
groupinfo = &keydb{
name = "椛椛"
limit int
vilginfo = &keydb{
db: &sql.Sqlite{},
}
modelinfo = &keydb{
db: &sql.Sqlite{},
}
limit = 50
dtype = [...]string{
"古风", "油画", "水彩画", "卡通画", "二次元", "浮世绘", "蒸汽波艺术", "low poly", "像素风格", "概念艺术", "未来主义", "赛博朋克", "写实风格", "洛丽塔风格", "巴洛克风格", "超现实主义",
}
)
func init() { // 插件主体
go func() {
process.GlobalInitMutex.Lock()
defer process.GlobalInitMutex.Unlock()
name = zero.BotConfig.NickName[0]
}()
engine := control.Register(serviceName, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "AI画图\n" +
Help: "文心AI画图\n" +
"基于百度文心的免费AI画图插件,\n因为是免费的,图片质量你懂的。\n" +
"key申请链接https://wenxin.baidu.com/moduleApi/key\n" +
"注意每个apikey每日上限50次,总上限500次请求。次数超过了请自行更新apikey\n" +
"- 为[自己/本群/QQ号/群+群号]设置AI画图key [API Key] [Secret Key]\n" +
"例:\n[为10086设置AI画图key 123 456]\n[为群10010设置AI画图key 789 101]\n" +
"key申请链接:https://wenxin.baidu.com/moduleApi/key\n" +
"key和erniemodel插件的key相同。\n" +
"注意:每个apikey每日上限50次,总上限500次请求。次数超过了请自行更新apikey\n" +
"- 为[自己/本群/QQ号/群+群号]设置画图key [API Key] [Secret Key]\n" +
"例:\n为自己设置画图key 123 456\n为10086设置画图key 123 456\n为群10010设置画图key 789 101\n" +
"- [bot名称]画几张[图片描述]的[图片类型][图片尺寸]\n" +
"————————————————————\n" +
"图片描述指南:\n图片主体细节词(请用逗号连接)\n官方prompt指南:https://wenxin.baidu.com/wenxin/docs#Ol7ece95m\n" +
@ -73,8 +87,8 @@ func init() { // 插件主体
"图片尺寸当前只支持:方图/长图/横图\n" +
"————————————————————\n" +
"指令示例:\n" +
"椛椛帮我画几张金凤凰背景绚烂高饱和古风仙境高清4K古风的油画方图",
PrivateDataFolder: "ernievilg",
name + "帮我画几张金凤凰背景绚烂高饱和古风仙境高清4K古风的油画方图",
PrivateDataFolder: "wenxinAI",
}).ApplySingle(single.New(
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
single.WithPostFn[int64](func(ctx *zero.Ctx) {
@ -87,8 +101,8 @@ func init() { // 插件主体
}),
))
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
groupinfo.db.DBPath = engine.DataFolder() + "keydb.db"
err := groupinfo.db.Open(time.Hour * 24)
vilginfo.db.DBPath = engine.DataFolder() + "ernieVilg.db"
err := vilginfo.db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return false
@ -101,8 +115,8 @@ func init() { // 插件主体
uid := -ctx.Event.UserID
gid := ctx.Event.GroupID
// 获取个人和群的key
userinfo, err1 := groupinfo.checkGroup(uid)
info, err2 := groupinfo.checkGroup(gid)
userinfo, err1 := vilginfo.checkGroup(uid, "vilg")
info, err2 := vilginfo.checkGroup(gid, "vilg")
switch {
// 如果是个人请求且报错
case gid == 0 && err1 != nil:
@ -189,7 +203,8 @@ func init() { // 插件主体
return
}
if status == "0" {
msg := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text("我画好了!"))}
lastTime := time.Duration(i * 10 * int(time.Second))
msg := message.Message{ctxext.FakeSenderForwardNode(ctx, message.Text("我画好了!\n本次绘画用了", lastTime))}
for _, imginfo := range picURL {
msg = append(msg,
ctxext.FakeSenderForwardNode(ctx,
@ -201,14 +216,14 @@ func init() { // 插件主体
break
}
}
err = groupinfo.update(gid)
err = vilginfo.update(gid, 1)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
}
process.SleepAbout1sTo2s()
ctx.SendChain(message.Text("累死了,今天我最多只能画", info.DayLimit-1, "张图哦"))
})
engine.OnRegex(`^为(群)?(自己|本群|\d+)设置AI画图key\s(.*[^\s$])\s(.+)$`, getdb).SetBlock(true).
engine.OnRegex(`^为(群)?(自己|本群|\d+)设置画图key\s(.*[^\s$])\s(.+)$`, getdb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
mode := ctx.State["regex_matched"].([]string)[1]
user := ctx.State["regex_matched"].([]string)[2]
@ -238,17 +253,267 @@ func init() { // 插件主体
}
dbID = -uid
}
err := groupinfo.insert(dbID, aKey, sKey)
err := vilginfo.insert(dbID, "vilg", aKey, sKey)
if err != nil {
ctx.SendChain(message.Text(serviceErr, err))
return
}
ctx.SendChain(message.Text("成功!"))
})
/*********************************************************/
en := control.Register(modelName, &ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Help: "文心AI文本处理\n" +
"基于百度文心AI的API文本处理\n" +
"key申请链接:https://wenxin.baidu.com/moduleApi/key\n" +
"key和ernievilg插件的key相同。\n" +
"注意:每个apikey每日上限200条,总上限2000条。次数超过了请自行更新apikey\n" +
"- 为[自己/本群/QQ号/群+群号]设置文心key [API Key] [Secret Key]\n" +
"例:\n为自己设置文心key 123 456\n为10086设置文心key 123 456\n为群10010设置文心key 789 101\n" +
"————————————————————\n" +
"- 文心作文 (x字的)[作文题目]\n" +
"————————————————————\n" +
"- 文心提案 (x字的)[文案标题]\n" +
"————————————————————\n" +
"- 文心摘要 (x字的)[文章内容]\n" +
"————————————————————\n" +
"- 文心小说 (x字的)[小说上文]" +
"————————————————————\n" +
"- 文心对联 [上联]\n" +
"————————————————————\n" +
"- 文心问答 [问题]" +
"————————————————————\n" +
"- 文心补全 [带“_”的填空题]" +
"————————————————————\n" +
"- 文心自定义 [prompt]\n" +
"prompt: [问题描述] [问题类型]:[题目] [解答类型]:[解题必带内容]\n" +
"指令示例:\n" +
"文心自定义 请写出下面这道题的解题过程。 题目:养殖场养鸭376只,养鸡的只数比鸭多258只,这个养殖场一共养鸭和鸡多少只? 解:\n" +
"文心自定义 1+1=?\n" +
"文心自定义 歌曲名:大风车转啊转 歌词:",
}).ApplySingle(single.New(
single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }),
single.WithPostFn[int64](func(ctx *zero.Ctx) {
ctx.Break()
ctx.Send(
message.ReplyWithMessage(ctx.Event.MessageID,
message.Text(zero.BotConfig.NickName[0], "正在给别人编辑,请不要打扰哦"),
),
)
}),
))
getmodeldb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
modelinfo.db.DBPath = engine.DataFolder() + "ernieModel.db"
err := modelinfo.db.Open(time.Hour * 24)
if err != nil {
ctx.SendChain(message.Text(modelErr, err))
return false
}
return true
})
en.OnRegex(`^为(群)?(自己|本群|\d+)设置文心key\s(.*[^\s$])\s(.+)$`, getmodeldb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
mode := ctx.State["regex_matched"].([]string)[1]
user := ctx.State["regex_matched"].([]string)[2]
aKey := ctx.State["regex_matched"].([]string)[3]
sKey := ctx.State["regex_matched"].([]string)[4]
dbID := -ctx.Event.UserID // 默认给自己
switch {
case mode != "": // 指定群的话
gid, err := strconv.ParseInt(user, 10, 64)
if err != nil {
ctx.SendChain(message.Text(modelErr, err))
return
}
dbID = gid
case user == "本群": // 用于本群
gid := ctx.Event.GroupID
if gid == 0 {
ctx.SendChain(message.Text(modelErr, "请指定群聊,或者使用指令;\n为群xxx设置AI画图key xxx xxx"))
return
}
dbID = gid
case user != "自己": // 给别人开key
uid, err := strconv.ParseInt(user, 10, 64)
if err != nil {
ctx.SendChain(message.Text(modelErr, err))
return
}
dbID = -uid
}
err := modelinfo.insert(dbID, "model", aKey, sKey)
if err != nil {
ctx.SendChain(message.Text(modelErr, err))
return
}
ctx.SendChain(message.Text("成功!"))
})
var erniemodel = map[string]int{
"作文": 1,
"提案": 2,
"摘要": 3,
"对联": 4,
"问答": 5,
"小说": 6,
"补全": 7,
"自定义": 8}
var erniePrompt = map[string]string{
"作文": "zuowen",
"提案": "adtext",
"摘要": "Summarization",
"对联": "couplet",
"问答": "Dialogue",
"小说": "novel",
"补全": "cloze"}
en.OnRegex(`^文心(作文|提案|摘要|小说)\s?((\d+)字的)?(.*)$`, getmodeldb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
uid := -ctx.Event.UserID
gid := ctx.Event.GroupID
// 获取个人和群的key
userinfo, err1 := modelinfo.checkGroup(uid, "model")
info, err2 := modelinfo.checkGroup(gid, "model")
switch {
// 如果是个人请求且报错
case gid == 0 && err1 != nil:
ctx.SendChain(message.Text(modelErr, err1))
return
// 如果群报错而个人没有,就切换成个人的
case err2 != nil && err1 == nil:
gid = uid
info = userinfo
// 如果都报错就以群为优先级
case err1 != nil && err2 != nil:
ctx.SendChain(message.Text(modelErr, err2))
return
}
// 判断使用次数
check := false
switch {
// 群和个人都没有次数了
case info.DayLimit == 0 && userinfo.DayLimit == 0:
ctx.SendChain(message.Text("今日请求次数已到200次了,明天在玩吧"))
return
// 个人还有次数的话
case info.DayLimit == 0 && userinfo.DayLimit != 0:
check = true
}
switch {
// 群和个人都没有总次数了
case info.MaxLimit == 0 && userinfo.MaxLimit == 0:
ctx.SendChain(message.Text("设置的key使用次数超过了限额,请更换key。"))
return
// 个人还有总次数的话
case info.MaxLimit == 0 && userinfo.MaxLimit != 0:
check = true
}
if check { // 如果只有个人有次数就切换回个人key
gid = uid
info = userinfo
}
// 调用API
modelStr := ctx.State["regex_matched"].([]string)[1]
mun := ctx.State["regex_matched"].([]string)[3]
minlen := 1
maxlen := 128
if mun != "" {
max, err := strconv.Atoi(mun)
if err != nil {
ctx.SendChain(message.Text(modelErr, err))
return
}
minlen = max
if max > 128 {
maxlen = max
}
}
keyword := ctx.State["regex_matched"].([]string)[4]
if len([]rune(keyword)) >= 1000 { // 描述不能超过1000
ctx.SendChain(message.Text("是你写作文还是我写?减少点!"))
return
}
result, err := model.GetResult(info.Token, erniemodel[modelStr], keyword, minlen, maxlen, erniePrompt[modelStr])
if err != nil {
ctx.SendChain(message.Text(modelErr, err))
return
}
if id := ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(keyword, "", result))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 请求超时!"))
}
err = modelinfo.update(gid, 1)
if err != nil {
ctx.SendChain(message.Text(modelErr, err))
}
})
en.OnRegex(`^文心(对联|问答|补全|自定义)\s?(.*)$`, getmodeldb).SetBlock(true).
Handle(func(ctx *zero.Ctx) {
uid := -ctx.Event.UserID
gid := ctx.Event.GroupID
// 获取个人和群的key
userinfo, err1 := modelinfo.checkGroup(uid, "model")
info, err2 := modelinfo.checkGroup(gid, "model")
switch {
// 如果是个人请求且报错
case gid == 0 && err1 != nil:
ctx.SendChain(message.Text(modelErr, err1))
return
// 如果群报错而个人没有,就切换成个人的
case err2 != nil && err1 == nil:
gid = uid
info = userinfo
// 如果都报错就以群为优先级
case err1 != nil && err2 != nil:
ctx.SendChain(message.Text(modelErr, err2))
return
}
// 判断使用次数
check := false
switch {
// 群和个人都没有次数了
case info.DayLimit == 0 && userinfo.DayLimit == 0:
ctx.SendChain(message.Text("今日请求次数已到200次了,明天在玩吧"))
return
// 个人还有次数的话
case info.DayLimit == 0 && userinfo.DayLimit != 0:
check = true
}
switch {
// 群和个人都没有总次数了
case info.MaxLimit == 0 && userinfo.MaxLimit == 0:
ctx.SendChain(message.Text("设置的key使用次数超过了限额,请更换key。"))
return
// 个人还有总次数的话
case info.MaxLimit == 0 && userinfo.MaxLimit != 0:
check = true
}
if check { // 如果只有个人有次数就切换回个人key
gid = uid
info = userinfo
}
// 创建任务
modelStr := ctx.State["regex_matched"].([]string)[1]
keyword := ctx.State["regex_matched"].([]string)[2]
if len([]rune(keyword)) >= 1000 { // 描述不能超过1000
ctx.SendChain(message.Text("你在写作文吗?减少点!"))
return
}
result, err := model.GetResult(info.Token, erniemodel[modelStr], keyword, 1, 128, erniePrompt[modelStr])
if err != nil {
ctx.SendChain(message.Text(modelErr, err))
return
}
if id := ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text(result))); id.ID() == 0 {
ctx.SendChain(message.Text("ERROR: 请求超时!"))
}
err = modelinfo.update(gid, 1)
if err != nil {
ctx.SendChain(message.Text(modelErr, err))
}
})
}
// 登记group的key
func (sql *keydb) insert(gid int64, akey, skey string) error {
func (sql *keydb) insert(gid int64, model, akey, skey string) error {
sql.Lock()
defer sql.Unlock()
// 给db文件创建表格(没有才创建)表格名称groupinfo表格结构apikey
@ -270,7 +535,12 @@ func (sql *keydb) insert(gid int64, akey, skey string) error {
ID: gid,
APIKey: akey,
SecretKey: skey,
MaxLimit: 500,
}
switch model {
case "vilg":
groupinfo.MaxLimit = 500
case "model":
groupinfo.MaxLimit = 2000
}
}
return sql.db.Insert("groupinfo", &groupinfo)
@ -278,12 +548,19 @@ func (sql *keydb) insert(gid int64, akey, skey string) error {
// 进行更新
groupinfo.APIKey = akey
groupinfo.SecretKey = skey
groupinfo.MaxLimit = 500
groupinfo.Token = ""
groupinfo.Updatetime = 0
switch model {
case "vilg":
groupinfo.MaxLimit = 500
case "model":
groupinfo.MaxLimit = 2000
}
return sql.db.Insert("groupinfo", &groupinfo)
}
// 获取group信息
func (sql *keydb) checkGroup(gid int64) (groupinfo apikey, err error) {
func (sql *keydb) checkGroup(gid int64, model string) (groupinfo apikey, err error) {
sql.Lock()
defer sql.Unlock()
// 给db文件创建表格(没有才创建)表格名称groupinfo表格结构apikey
@ -291,12 +568,20 @@ func (sql *keydb) checkGroup(gid int64) (groupinfo apikey, err error) {
if err != nil {
return
}
switch model {
case "vilg":
limit = 50
model = "画图"
case "model":
limit = 200
model = "文心"
}
// 先判断该群是否已经设置过key了
if ok := sql.db.CanFind("groupinfo", "where ID is "+strconv.FormatInt(gid, 10)); !ok {
if gid > 0 {
err = errors.New("该群没有设置过apikey请前往https://wenxin.baidu.com/moduleApi/key获取key值后发送指令:\n为本群设置AI画图key [API Key] [Secret Key]")
err = errors.New("该群没有设置过apikey请前往https://wenxin.baidu.com/moduleApi/key获取key值后发送指令:\n为本群设置" + model + "key [API Key] [Secret Key]\n或\n为自己设置" + model + "key [API Key] [Secret Key]")
} else {
err = errors.New("你没有设置过apikey请前往https://wenxin.baidu.com/moduleApi/key获取key值后发送指令:\n为自己设置AI画图key [API Key] [Secret Key]")
err = errors.New("你没有设置过apikey请前往https://wenxin.baidu.com/moduleApi/key获取key值后发送指令:\n为自己设置" + model + "key [API Key] [Secret Key]")
}
return
}
@ -314,7 +599,7 @@ func (sql *keydb) checkGroup(gid int64) (groupinfo apikey, err error) {
return
}
// 如果token有效期过期
if time.Since(time.Unix(groupinfo.Updatetime, 0)).Hours() > 24 {
if time.Since(time.Unix(groupinfo.Updatetime, 0)).Hours() > 24 || groupinfo.Token == "" {
token, err1 := wenxin.GetToken(groupinfo.APIKey, groupinfo.SecretKey)
if err1 != nil {
err = err1
@ -350,8 +635,8 @@ func (sql *keydb) checkGroup(gid int64) (groupinfo apikey, err error) {
return
}
// 记录次数(-1)
func (sql *keydb) update(gid int64) error {
// 记录次数(-sub)
func (sql *keydb) update(gid int64, sub int) error {
sql.Lock()
defer sql.Unlock()
// 给db文件创建表格(没有才创建)表格名称groupinfo表格结构apikey
@ -365,8 +650,8 @@ func (sql *keydb) update(gid int64) error {
if err != nil {
return err
}
groupinfo.MaxLimit--
groupinfo.DayLimit--
groupinfo.MaxLimit -= sub
groupinfo.DayLimit -= sub
err = sql.db.Insert("groupinfo", &groupinfo)
if err != nil {
return err