mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 13:59:39 +08:00
322 lines
11 KiB
Go
322 lines
11 KiB
Go
// 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
|
|
}
|