mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 05:30:07 +08:00
chore: del vtbxxx due to 跑路
This commit is contained in:
parent
a72bec15a9
commit
c29b1238c2
10
README.md
10
README.md
@ -1272,16 +1272,6 @@ print("run[CQ:image,file="+j["img"]+"]")
|
||||
|
||||
- [x] 更新vtb
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>vtb点歌</summary>
|
||||
|
||||
`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtbmusic"`
|
||||
|
||||
- [x] vtb点歌
|
||||
|
||||
- [x] vtb随机点歌
|
||||
|
||||
</details>
|
||||
<details>
|
||||
<summary>钱包</summary>
|
||||
|
||||
2
main.go
2
main.go
@ -131,8 +131,6 @@ import (
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/tracemoe" // 搜番
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/translation" // 翻译
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vitsnyaru" // vits猫雷
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtbmusic" // vtb点歌
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/vtbquotation" // vtb语录
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wallet" // 钱包
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/wantquotes" // 据意查句
|
||||
_ "github.com/FloatTech/ZeroBot-Plugin/plugin/warframeapi" // warframeAPI插件
|
||||
|
||||
@ -1,321 +0,0 @@
|
||||
// Package vtbmusic vtb点歌
|
||||
package vtbmusic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/FloatTech/floatbox/binary"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
)
|
||||
|
||||
const (
|
||||
getGroupListURL = "https://aqua.chat/v1/GetGroupsList"
|
||||
getMusicListURL = "https://aqua.chat/v1/GetMusicList"
|
||||
fileURL = "https://cdn.aqua.chat/"
|
||||
musicListBody = `{"search":{"condition":"VocalId","keyword":"%v"},"sortField":"CreateTime","sortType":"desc","pageIndex":1,"pageRows":10000}`
|
||||
)
|
||||
|
||||
type groupsList struct {
|
||||
Total int `json:"Total"`
|
||||
Data []struct {
|
||||
ID string `json:"Id"`
|
||||
CreateTime string `json:"CreateTime"`
|
||||
Name string `json:"Name"`
|
||||
GroupImg string `json:"GroupImg"`
|
||||
VocalList []struct {
|
||||
ID string `json:"Id"`
|
||||
CreateTime string `json:"CreateTime"`
|
||||
ChineseName string `json:"ChineseName"`
|
||||
OriginName string `json:"OriginName"`
|
||||
AvatarImg string `json:"AvatarImg"`
|
||||
} `json:"VocalList"`
|
||||
} `json:"Data"`
|
||||
Success bool `json:"Success"`
|
||||
ErrorCode int `json:"ErrorCode"`
|
||||
Msg interface{} `json:"Msg"`
|
||||
}
|
||||
|
||||
type musicList struct {
|
||||
Total int `json:"Total"`
|
||||
Data []struct {
|
||||
ID string `json:"Id"`
|
||||
CreateTime string `json:"CreateTime"`
|
||||
PublishTime interface{} `json:"PublishTime"`
|
||||
CreatorID interface{} `json:"CreatorId"`
|
||||
CreatorRealName interface{} `json:"CreatorRealName"`
|
||||
Deleted bool `json:"Deleted"`
|
||||
OriginName string `json:"OriginName"`
|
||||
VocalID string `json:"VocalId"`
|
||||
VocalName string `json:"VocalName"`
|
||||
CoverImg string `json:"CoverImg"`
|
||||
Music string `json:"Music"`
|
||||
Lyric interface{} `json:"Lyric"`
|
||||
CDN string `json:"CDN"`
|
||||
BiliBili interface{} `json:"BiliBili"`
|
||||
YouTube interface{} `json:"YouTube"`
|
||||
Twitter interface{} `json:"Twitter"`
|
||||
Likes interface{} `json:"Likes"`
|
||||
Length float64 `json:"Length"`
|
||||
Label interface{} `json:"Label"`
|
||||
IsLike bool `json:"isLike"`
|
||||
Duration float64 `json:"Duration"`
|
||||
Source interface{} `json:"Source"`
|
||||
SourceName interface{} `json:"SourceName"`
|
||||
Statis struct {
|
||||
PlayCount int `json:"PlayCount"`
|
||||
CommentCount int `json:"CommentCount"`
|
||||
LikeCount int `json:"LikeCount"`
|
||||
ShareCount int `json:"ShareCount"`
|
||||
} `json:"Statis"`
|
||||
VocalList []struct {
|
||||
ID string `json:"Id"`
|
||||
Cn string `json:"cn"`
|
||||
Jp string `json:"jp"`
|
||||
En string `json:"en"`
|
||||
Originlang string `json:"originlang"`
|
||||
} `json:"VocalList"`
|
||||
} `json:"Data"`
|
||||
Success bool `json:"Success"`
|
||||
ErrorCode int `json:"ErrorCode"`
|
||||
Msg interface{} `json:"Msg"`
|
||||
}
|
||||
|
||||
func init() { // 插件主体
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "vtbmusic.com点歌",
|
||||
Help: "- vtb点歌\n" +
|
||||
"- vtb随机点歌",
|
||||
PrivateDataFolder: "vtbmusic",
|
||||
})
|
||||
storePath := engine.DataFolder()
|
||||
// 开启
|
||||
engine.OnFullMatch(`vtb点歌`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
next := zero.NewFutureEvent("message", 999, false, ctx.CheckSession(), zero.RegexRule(`^\d+$`))
|
||||
recv, cancel := next.Repeat()
|
||||
defer cancel()
|
||||
i := 0
|
||||
paras := [3]int{}
|
||||
data, err := web.PostData(getGroupListURL, "application/json", strings.NewReader(`{"PageIndex":1,"PageRows":9999}`))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
var (
|
||||
gl groupsList
|
||||
ml musicList
|
||||
num int
|
||||
imageBytes []byte
|
||||
)
|
||||
err = json.Unmarshal(data, &gl)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
tex := "请输入群组序号\n"
|
||||
for i, v := range gl.Data {
|
||||
tex += fmt.Sprintf("%d. %s\n", i, v.Name)
|
||||
}
|
||||
imageBytes, err = text.RenderToBase64(tex, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("base64://"+binary.BytesToString(imageBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-time.After(time.Second * 120):
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("vtb点歌超时"))
|
||||
return
|
||||
case c := <-recv:
|
||||
msg := c.Event.Message.ExtractPlainText()
|
||||
num, err = strconv.Atoi(msg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("请输入数字!"))
|
||||
continue
|
||||
}
|
||||
switch i {
|
||||
case 0:
|
||||
if num < 0 || num >= len(gl.Data) {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("序号非法!"))
|
||||
continue
|
||||
}
|
||||
if len(gl.Data[num].VocalList) == 0 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无内容, 点歌失败"))
|
||||
return
|
||||
}
|
||||
paras[0] = num
|
||||
tex = "请输入vtb序号\n"
|
||||
for i, v := range gl.Data[paras[0]].VocalList {
|
||||
tex += fmt.Sprintf("%d. %s\n", i, v.OriginName)
|
||||
}
|
||||
imageBytes, err = text.RenderToBase64(tex, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("base64://"+binary.BytesToString(imageBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
case 1:
|
||||
if num < 0 || num >= len(gl.Data[paras[0]].VocalList) {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("序号非法!"))
|
||||
continue
|
||||
}
|
||||
paras[1] = num
|
||||
data, err := web.PostData(getMusicListURL, "application/json", strings.NewReader(fmt.Sprintf(musicListBody, gl.Data[paras[0]].VocalList[paras[1]].ID)))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &ml)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if len(ml.Data) == 0 {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("无内容, 点歌失败"))
|
||||
return
|
||||
}
|
||||
tex = "请输入歌曲序号\n"
|
||||
for i, v := range ml.Data {
|
||||
tex += fmt.Sprintf("%d. %s\n", i, v.OriginName)
|
||||
}
|
||||
imageBytes, err = text.RenderToBase64(tex, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("base64://"+binary.BytesToString(imageBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
case 2:
|
||||
if num < 0 || num >= len(ml.Data) {
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("序号非法!"))
|
||||
continue
|
||||
}
|
||||
paras[2] = num
|
||||
// 最后播放歌曲
|
||||
groupName := gl.Data[paras[0]].Name
|
||||
vtbName := gl.Data[paras[0]].VocalList[paras[1]].OriginName
|
||||
musicName := ml.Data[paras[2]].OriginName
|
||||
recURL := fileURL + ml.Data[paras[2]].Music
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("请欣赏", groupName, "-", vtbName, "的《", musicName, "》"))
|
||||
recordFile := storePath + fmt.Sprintf("%d-%d-%d", paras[0], paras[1], paras[2]) + path.Ext(recURL)
|
||||
if file.IsExist(recordFile) {
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + recordFile))
|
||||
return
|
||||
}
|
||||
err = dlrec(recordFile, recURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + recordFile))
|
||||
return
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch(`vtb随机点歌`).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
var (
|
||||
paras = [3]int{}
|
||||
gl groupsList
|
||||
ml musicList
|
||||
)
|
||||
data, err := web.PostData(getGroupListURL, "application/json", strings.NewReader(`{"PageIndex":1,"PageRows":9999}`))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &gl)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if len(gl.Data) == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 数组为空"))
|
||||
return
|
||||
}
|
||||
paras[0] = rand.Intn(len(gl.Data))
|
||||
for len(gl.Data[paras[0]].VocalList) == 0 {
|
||||
paras[0] = rand.Intn(len(gl.Data))
|
||||
}
|
||||
paras[1] = rand.Intn(len(gl.Data[paras[0]].VocalList))
|
||||
data, err = web.PostData(getMusicListURL, "application/json", strings.NewReader(fmt.Sprintf(musicListBody, gl.Data[paras[0]].VocalList[paras[1]].ID)))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &ml)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
for len(ml.Data) == 0 {
|
||||
paras[1] = rand.Intn(len(gl.Data[paras[0]].VocalList))
|
||||
data, err = web.PostData(getMusicListURL, "application/json", strings.NewReader(fmt.Sprintf(musicListBody, gl.Data[paras[0]].VocalList[paras[1]].ID)))
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
err = json.Unmarshal(data, &ml)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
paras[2] = rand.Intn(len(ml.Data))
|
||||
// 最后播放歌曲
|
||||
groupName := gl.Data[paras[0]].Name
|
||||
vtbName := gl.Data[paras[0]].VocalList[paras[1]].OriginName
|
||||
musicName := ml.Data[paras[2]].OriginName
|
||||
recURL := fileURL + ml.Data[paras[2]].Music
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("请欣赏", groupName, "-", vtbName, "的《", musicName, "》"))
|
||||
recordFile := storePath + fmt.Sprintf("%d-%d-%d", paras[0], paras[1], paras[2]) + path.Ext(recURL)
|
||||
if file.IsExist(recordFile) {
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + recordFile))
|
||||
return
|
||||
}
|
||||
err = dlrec(recordFile, recURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + recordFile))
|
||||
})
|
||||
}
|
||||
|
||||
func dlrec(recordFile, recordURL string) error {
|
||||
if file.IsNotExist(recordFile) {
|
||||
data, err := web.RequestDataWithHeaders(web.NewTLS12Client(), recordURL, "GET", func(r *http.Request) error {
|
||||
r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
r.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
|
||||
return nil
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(recordFile, data, 0666)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -1,325 +0,0 @@
|
||||
// Package model vtb数据库操作
|
||||
package model
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
"github.com/jinzhu/gorm"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// VtbDB vtb 数据库
|
||||
type VtbDB gorm.DB
|
||||
|
||||
// Initialize ...
|
||||
func Initialize(dbpath string) *VtbDB {
|
||||
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(FirstCategory{}).AutoMigrate(SecondCategory{}).AutoMigrate(ThirdCategory{})
|
||||
return (*VtbDB)(gdb)
|
||||
}
|
||||
|
||||
// Open ...
|
||||
func Open(dbpath string) (*VtbDB, error) {
|
||||
db, err := gorm.Open("sqlite3", dbpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return (*VtbDB)(db), nil
|
||||
}
|
||||
|
||||
// FirstCategory 第一品类
|
||||
type FirstCategory struct {
|
||||
gorm.Model
|
||||
FirstCategoryIndex int64 `gorm:"column:first_category_index"`
|
||||
FirstCategoryName string `gorm:"column:first_category_name"`
|
||||
FirstCategoryUID string `gorm:"column:first_category_uid"`
|
||||
FirstCategoryDescription string `gorm:"column:first_category_description;type:varchar(1024)"`
|
||||
FirstCategoryIconPath string `gorm:"column:first_category_icon_path"`
|
||||
}
|
||||
|
||||
// TableName ...
|
||||
func (FirstCategory) TableName() string {
|
||||
return "first_category"
|
||||
}
|
||||
|
||||
// SecondCategory 第二品类
|
||||
type SecondCategory struct {
|
||||
gorm.Model
|
||||
SecondCategoryIndex int64 `gorm:"column:second_category_index"`
|
||||
FirstCategoryUID string `gorm:"column:first_category_uid;association_foreignkey:first_category_uid"`
|
||||
SecondCategoryName string `gorm:"column:second_category_name"`
|
||||
SecondCategoryAuthor string `gorm:"column:second_category_author"`
|
||||
SecondCategoryDescription string `gorm:"column:second_category_description"`
|
||||
}
|
||||
|
||||
// TableName ...
|
||||
func (SecondCategory) TableName() string {
|
||||
return "second_category"
|
||||
}
|
||||
|
||||
// ThirdCategory 第三品类
|
||||
type ThirdCategory struct {
|
||||
gorm.Model
|
||||
ThirdCategoryIndex int64 `gorm:"column:third_category_index"`
|
||||
SecondCategoryIndex int64 `gorm:"column:second_category_index"`
|
||||
FirstCategoryUID string `gorm:"column:first_category_uid"`
|
||||
ThirdCategoryName string `gorm:"column:third_category_name"`
|
||||
ThirdCategoryPath string `gorm:"column:third_category_path"`
|
||||
ThirdCategoryAuthor string `gorm:"column:third_category_author"`
|
||||
ThirdCategoryDescription string `gorm:"column:third_category_description"`
|
||||
}
|
||||
|
||||
// TableName ...
|
||||
func (ThirdCategory) TableName() string {
|
||||
return "third_category"
|
||||
}
|
||||
|
||||
// GetAllFirstCategoryMessage 取出所有vtb
|
||||
func (vdb *VtbDB) GetAllFirstCategoryMessage() (string, error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
firstStepMessage := "请选择一个vtb并发送序号:\n"
|
||||
var fcl []FirstCategory
|
||||
err := db.Model(&FirstCategory{}).Find(&fcl).Error
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for _, v := range fcl {
|
||||
firstStepMessage += strconv.FormatInt(v.FirstCategoryIndex, 10) + ". " + v.FirstCategoryName + "\n"
|
||||
}
|
||||
return firstStepMessage, nil
|
||||
}
|
||||
|
||||
// GetAllSecondCategoryMessageByFirstIndex 取得同一个vtb所有语录类别
|
||||
func (vdb *VtbDB) GetAllSecondCategoryMessageByFirstIndex(firstIndex int) (string, error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
secondStepMessage := "请选择一个语录类别并发送序号:\n"
|
||||
var scl []SecondCategory
|
||||
var fc FirstCategory
|
||||
db.Model(FirstCategory{}).Where("first_category_index = ?", firstIndex).First(&fc)
|
||||
err := db.Model(&SecondCategory{}).Find(&scl, "first_category_uid = ?", fc.FirstCategoryUID).Error
|
||||
if err != nil || len(scl) == 0 {
|
||||
return "", err
|
||||
}
|
||||
for _, v := range scl {
|
||||
secondStepMessage += strconv.FormatInt(v.SecondCategoryIndex, 10) + ". " + v.SecondCategoryName + "\n"
|
||||
}
|
||||
return secondStepMessage, nil
|
||||
}
|
||||
|
||||
// GetAllThirdCategoryMessageByFirstIndexAndSecondIndex 取得同一个vtb同个类别的所有语录
|
||||
func (vdb *VtbDB) GetAllThirdCategoryMessageByFirstIndexAndSecondIndex(firstIndex, secondIndex int) (string, error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
thirdStepMessage := "请选择一个语录并发送序号:\n"
|
||||
var fc FirstCategory
|
||||
db.Model(FirstCategory{}).Where("first_category_index = ?", firstIndex).First(&fc)
|
||||
var tcl []ThirdCategory
|
||||
err := db.Model(&ThirdCategory{}).Find(&tcl, "first_category_uid = ? and second_category_index = ?", fc.FirstCategoryUID, secondIndex).Error
|
||||
if err != nil || len(tcl) == 0 {
|
||||
return "", err
|
||||
}
|
||||
for _, v := range tcl {
|
||||
thirdStepMessage = thirdStepMessage + strconv.FormatInt(v.ThirdCategoryIndex, 10) + ". " + v.ThirdCategoryName + "\n"
|
||||
}
|
||||
return thirdStepMessage, nil
|
||||
}
|
||||
|
||||
// GetThirdCategory ...
|
||||
func (vdb *VtbDB) GetThirdCategory(firstIndex, secondIndex, thirdIndex int) ThirdCategory {
|
||||
db := (*gorm.DB)(vdb)
|
||||
var fc FirstCategory
|
||||
db.Model(FirstCategory{}).Where("first_category_index = ?", firstIndex).First(&fc)
|
||||
var tc ThirdCategory
|
||||
db.Model(&ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ? and third_category_index = ?", fc.FirstCategoryUID, secondIndex, thirdIndex).Take(&tc)
|
||||
return tc
|
||||
}
|
||||
|
||||
// RandomVtb ...
|
||||
func (vdb *VtbDB) RandomVtb() ThirdCategory {
|
||||
db := (*gorm.DB)(vdb)
|
||||
var count int
|
||||
var tc ThirdCategory
|
||||
db.Model(&ThirdCategory{}).Count(&count).Offset(rand.Intn(count)).Take(&tc)
|
||||
return tc
|
||||
}
|
||||
|
||||
// GetFirstCategoryByFirstUID ...
|
||||
func (vdb *VtbDB) GetFirstCategoryByFirstUID(firstUID string) FirstCategory {
|
||||
db := (*gorm.DB)(vdb)
|
||||
var fc FirstCategory
|
||||
db.Model(FirstCategory{}).Take(&fc, "first_category_uid = ?", firstUID)
|
||||
return fc
|
||||
}
|
||||
|
||||
// Close ...
|
||||
func (vdb *VtbDB) Close() error {
|
||||
db := (*gorm.DB)(vdb)
|
||||
return db.Close()
|
||||
}
|
||||
|
||||
const vtbURL = "https://vtbkeyboard.moe/api/get_vtb_list"
|
||||
|
||||
// GetVtbList ...
|
||||
func (vdb *VtbDB) GetVtbList() (uidList []string, err error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", vtbURL, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 自定义Header
|
||||
req.Header.Set("User-Agent", web.RandUA())
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
bytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
vtbListStr, err := strconv.Unquote(strings.ReplaceAll(strconv.Quote(string(bytes)), `\\u`, `\u`))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
count := gjson.Get(vtbListStr, "#").Int()
|
||||
for i := int64(0); i < count; i++ {
|
||||
item := gjson.Get(vtbListStr, strconv.FormatInt(i, 10))
|
||||
log.Debugln(item)
|
||||
fc := FirstCategory{
|
||||
FirstCategoryIndex: i,
|
||||
FirstCategoryName: item.Get("name").String(),
|
||||
FirstCategoryDescription: item.Get("description").String(),
|
||||
FirstCategoryIconPath: item.Get("icon_path").String(),
|
||||
FirstCategoryUID: item.Get("uid").String(),
|
||||
}
|
||||
log.Debugln(fc)
|
||||
|
||||
if err := db.Model(&FirstCategory{}).First(&fc, "first_category_uid = ?", fc.FirstCategoryUID).Error; err != nil {
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
db.Model(&FirstCategory{}).Create(&fc) // newUser not user
|
||||
}
|
||||
} else {
|
||||
db.Model(&FirstCategory{}).Where("first_category_uid = ?", fc.FirstCategoryUID).Update(
|
||||
map[string]any{
|
||||
"first_category_index": i,
|
||||
"first_category_name": item.Get("name").String(),
|
||||
"first_category_description": item.Get("description").String(),
|
||||
"first_category_icon_path": item.Get("icon_path").String(),
|
||||
})
|
||||
}
|
||||
uidList = append(uidList, fc.FirstCategoryUID)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// StoreVtb ...
|
||||
func (vdb *VtbDB) StoreVtb(uid string) (err error) {
|
||||
db := (*gorm.DB)(vdb)
|
||||
vtbURL := "https://vtbkeyboard.moe/api/get_vtb_page?uid=" + uid
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", vtbURL, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 自定义Header
|
||||
req.Header.Set("User-Agent", web.RandUA())
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
bytes, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
vtbStr, err := strconv.Unquote(strings.ReplaceAll(strconv.Quote(string(bytes)), `\\u`, `\u`))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
secondCount := gjson.Get(vtbStr, "data.voices.#").Int()
|
||||
log.Debugln("二级品类一共有", secondCount)
|
||||
for secondIndex := int64(0); secondIndex < secondCount; secondIndex++ {
|
||||
secondItem := gjson.Get(vtbStr, "data.voices."+strconv.FormatInt(secondIndex, 10))
|
||||
log.Debugln(secondItem)
|
||||
sc := SecondCategory{
|
||||
SecondCategoryName: secondItem.Get("categoryName").String(),
|
||||
SecondCategoryIndex: secondIndex,
|
||||
SecondCategoryAuthor: secondItem.Get("author").String(),
|
||||
SecondCategoryDescription: secondItem.Get("categoryDescription.zh-CN").String(),
|
||||
FirstCategoryUID: uid,
|
||||
}
|
||||
|
||||
if err := db.Model(&SecondCategory{}).First(&sc, "first_category_uid = ? and second_category_index = ?", uid, secondIndex).Error; err != nil {
|
||||
// error handling...
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
db.Model(&SecondCategory{}).Create(&sc) // newUser not user
|
||||
}
|
||||
} else {
|
||||
db.Model(&SecondCategory{}).Where("first_category_uid = ? and second_category_index = ?", uid, secondIndex).Update(
|
||||
map[string]any{
|
||||
"second_category_name": secondItem.Get("categoryName").String(),
|
||||
"second_category_author": secondItem.Get("author").String(),
|
||||
"second_category_description": secondItem.Get("categoryDescription.zh-CN").String(),
|
||||
})
|
||||
}
|
||||
thirdCount := secondItem.Get("voiceList.#").Int()
|
||||
log.Debugln("三级品类一共有", thirdCount)
|
||||
for thirdIndex := int64(0); thirdIndex < thirdCount; thirdIndex++ {
|
||||
thirdItem := secondItem.Get("voiceList." + strconv.FormatInt(thirdIndex, 10))
|
||||
log.Debugln(thirdItem)
|
||||
tc := ThirdCategory{
|
||||
ThirdCategoryName: thirdItem.Get("name").String(),
|
||||
ThirdCategoryIndex: thirdIndex,
|
||||
ThirdCategoryDescription: thirdItem.Get("description.zh-CN").String(),
|
||||
FirstCategoryUID: uid,
|
||||
SecondCategoryIndex: secondIndex,
|
||||
ThirdCategoryPath: thirdItem.Get("path").String(),
|
||||
ThirdCategoryAuthor: thirdItem.Get("author").String(),
|
||||
}
|
||||
log.Debugln(tc)
|
||||
|
||||
if err := db.Model(&ThirdCategory{}).First(&tc, "first_category_uid = ? and second_category_index = ? and third_category_index = ?",
|
||||
uid, secondIndex, thirdIndex).Error; err != nil {
|
||||
if gorm.IsRecordNotFoundError(err) {
|
||||
db.Model(&ThirdCategory{}).Create(&tc) // newUser not user
|
||||
}
|
||||
} else {
|
||||
db.Model(&ThirdCategory{}).Where("first_category_uid = ? and second_category_index = ? and third_category_index = ?",
|
||||
uid, secondIndex, thirdIndex).Update(
|
||||
map[string]any{
|
||||
"third_category_name": thirdItem.Get("name").String(),
|
||||
"third_category_description": thirdItem.Get("description.zh-CN").String(),
|
||||
"third_category_path": thirdItem.Get("path").String(),
|
||||
"third_category_author": thirdItem.Get("author").String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -1,297 +0,0 @@
|
||||
// Package vtbquotation vtb经典语录
|
||||
package vtbquotation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
zero "github.com/wdvxdr1123/ZeroBot"
|
||||
"github.com/wdvxdr1123/ZeroBot/message"
|
||||
"github.com/wdvxdr1123/ZeroBot/utils/helper"
|
||||
|
||||
fcext "github.com/FloatTech/floatbox/ctxext"
|
||||
"github.com/FloatTech/floatbox/file"
|
||||
"github.com/FloatTech/floatbox/web"
|
||||
ctrl "github.com/FloatTech/zbpctrl"
|
||||
"github.com/FloatTech/zbputils/control"
|
||||
"github.com/FloatTech/zbputils/img/text"
|
||||
|
||||
"github.com/FloatTech/ZeroBot-Plugin/plugin/vtbquotation/model"
|
||||
)
|
||||
|
||||
var reg = regexp.MustCompile(".*/(.*)")
|
||||
|
||||
func init() {
|
||||
engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||||
DisableOnDefault: false,
|
||||
Brief: "vtb语录",
|
||||
Help: "- vtb语录\n- 随机vtb\n- 更新vtb\n来源: vtbkeyboard.moe",
|
||||
PublicDataFolder: "VtbQuotation",
|
||||
})
|
||||
dbfile := engine.DataFolder() + "vtb.db"
|
||||
storePath := engine.DataFolder() + "store/"
|
||||
getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool {
|
||||
err := os.MkdirAll(storePath, 0755)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
_, err = engine.GetLazyData("vtb.db", false)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
engine.OnFullMatch("vtb语录", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
indexs := [3]int{}
|
||||
echo, cancel := ctx.FutureEvent("message",
|
||||
ctx.CheckSession()). // 只复读开启复读模式的人的消息
|
||||
Repeat() // 不断监听复读
|
||||
db, err := model.Open(dbfile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
defer cancel()
|
||||
r, err := db.GetAllFirstCategoryMessage()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
firstStepImageBytes, err := text.RenderToBase64(r, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("base64://"+helper.BytesToString(firstStepImageBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
// 步骤0,1,2,依次选择3个类别
|
||||
step := 0
|
||||
// 错误次数
|
||||
errorCount := 0
|
||||
for {
|
||||
select {
|
||||
case c := <-echo: // 接收到需要复读的消息
|
||||
// 错误次数达到3次,结束命令
|
||||
if errorCount >= 3 {
|
||||
ctx.SendChain(message.Reply(c.Event.MessageID), message.Text("输入错误太多,请重新发指令"))
|
||||
return
|
||||
}
|
||||
msg := c.Event.Message.ExtractPlainText()
|
||||
num, err := strconv.Atoi(msg)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Reply(c.Event.MessageID), message.Text("请输入正确的序号,三次输入错误,指令可退出重输"))
|
||||
errorCount++
|
||||
continue
|
||||
}
|
||||
switch step {
|
||||
case 0:
|
||||
indexs[0] = num
|
||||
secondStepMessage, err := db.GetAllSecondCategoryMessageByFirstIndex(indexs[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if secondStepMessage == "" {
|
||||
ctx.SendChain(message.Reply(c.Event.MessageID), message.Text("你选择的序号没有内容,请重新选择,三次输入错误,指令可退出重输"))
|
||||
r, err := db.GetAllFirstCategoryMessage()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
firstStepImageBytes, err := text.RenderToBase64(r, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("base64://"+helper.BytesToString(firstStepImageBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
errorCount++
|
||||
} else {
|
||||
secondStepMessageBytes, err := text.RenderToBase64(secondStepMessage, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("base64://"+helper.BytesToString(secondStepMessageBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
step++
|
||||
}
|
||||
|
||||
case 1:
|
||||
indexs[1] = num
|
||||
thirdStepMessage, err := db.GetAllThirdCategoryMessageByFirstIndexAndSecondIndex(indexs[0], indexs[1])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if thirdStepMessage == "" {
|
||||
ctx.SendChain(message.Reply(c.Event.MessageID), message.Text("你选择的序号没有内容,请重新选择,三次输入错误,指令可退出重输"))
|
||||
r, err := db.GetAllSecondCategoryMessageByFirstIndex(indexs[0])
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
secondStepMessageBytes, err := text.RenderToBase64(r, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("base64://"+helper.BytesToString(secondStepMessageBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
errorCount++
|
||||
} else {
|
||||
thirdStepMessageBytes, err := text.RenderToBase64(thirdStepMessage, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("base64://"+helper.BytesToString(thirdStepMessageBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
step++
|
||||
}
|
||||
case 2:
|
||||
indexs[2] = num
|
||||
tc := db.GetThirdCategory(indexs[0], indexs[1], indexs[2])
|
||||
recURL := tc.ThirdCategoryPath
|
||||
if recURL == "" {
|
||||
ctx.SendChain(message.Reply(c.Event.MessageID), message.Text("没有内容请重新选择,三次输入错误,指令可退出重输"))
|
||||
r, err := db.GetAllFirstCategoryMessage()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
firstStepImageBytes, err := text.RenderToBase64(r, text.FontFile, 400, 20)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
if id := ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Image("base64://"+helper.BytesToString(firstStepImageBytes))); id.ID() == 0 {
|
||||
ctx.SendChain(message.Text("ERROR: 可能被风控了"))
|
||||
}
|
||||
errorCount++
|
||||
step = 1
|
||||
} else {
|
||||
if reg.MatchString(recURL) {
|
||||
recURL = strings.ReplaceAll(recURL, reg.FindStringSubmatch(recURL)[1], url.QueryEscape(reg.FindStringSubmatch(recURL)[1]))
|
||||
recURL = strings.ReplaceAll(recURL, "+", "%20")
|
||||
}
|
||||
ctx.SendChain(message.Reply(c.Event.MessageID), message.Text("请欣赏《"+tc.ThirdCategoryName+"》"))
|
||||
recordFile := storePath + fmt.Sprintf("%d-%d-%d", indexs[0], indexs[1], indexs[2]) + path.Ext(recURL)
|
||||
if file.IsExist(recordFile) {
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + recordFile))
|
||||
return
|
||||
}
|
||||
err = initRecord(recordFile, recURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + recordFile))
|
||||
return
|
||||
}
|
||||
default:
|
||||
return
|
||||
}
|
||||
case <-time.After(time.Second * 60):
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("vtb语录指令过期"))
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("随机vtb", getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
db, err := model.Open(dbfile)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
tc := db.RandomVtb()
|
||||
fc := db.GetFirstCategoryByFirstUID(tc.FirstCategoryUID)
|
||||
if (tc != model.ThirdCategory{}) && (fc != model.FirstCategory{}) {
|
||||
recURL := tc.ThirdCategoryPath
|
||||
if reg.MatchString(recURL) {
|
||||
recURL = strings.ReplaceAll(recURL, reg.FindStringSubmatch(recURL)[1], url.QueryEscape(reg.FindStringSubmatch(recURL)[1]))
|
||||
recURL = strings.ReplaceAll(recURL, "+", "%20")
|
||||
}
|
||||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("请欣赏"+fc.FirstCategoryName+"的《"+tc.ThirdCategoryName+"》"))
|
||||
recordFile := storePath + fmt.Sprintf("%d-%d-%d", fc.FirstCategoryIndex, tc.SecondCategoryIndex, tc.ThirdCategoryIndex) + path.Ext(recURL)
|
||||
if file.IsExist(recordFile) {
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + recordFile))
|
||||
return
|
||||
}
|
||||
err = initRecord(recordFile, recURL)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + recordFile))
|
||||
}
|
||||
})
|
||||
engine.OnFullMatch("更新vtb", zero.SuperUserPermission, getdb).SetBlock(true).
|
||||
Handle(func(ctx *zero.Ctx) {
|
||||
ctx.Send("少女祈祷中......")
|
||||
db := model.Initialize(dbfile)
|
||||
if db != nil {
|
||||
vl, err := db.GetVtbList()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
for _, v := range vl {
|
||||
err = db.StoreVtb(v)
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
err = db.Close()
|
||||
if err != nil {
|
||||
ctx.SendChain(message.Text("ERROR: ", err))
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.Send("vtb数据库已更新")
|
||||
})
|
||||
}
|
||||
|
||||
func initRecord(recordFile, recordURL string) error {
|
||||
if file.IsNotExist(recordFile) {
|
||||
client := web.NewTLS12Client()
|
||||
req, _ := http.NewRequest("GET", recordURL, nil)
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.WriteFile(recordFile, data, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user