mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 13:59:39 +08:00
为猜歌插件添加config (#285)
* ✨ 猜歌添加config * 📚 猜歌帮助信息更新 * 📚 猜歌帮助信息更新 * ✨ 猜歌错误信息继承 * ✨ 错误处理 * ✨ 错误处理ep2 * 🐛 猜歌插件bug修正和命名修改 * ✨ 猜歌插件不再使用gjson * Update struct.go * 修复-动漫2无法下载歌曲问题 * 🐛 Resolve Compilation error * 🐛 Resolve Lint * 🐛 Resolve Lint Co-authored-by: 方柳煜 <101934327+fangliuyu@users.noreply.github.com>
This commit is contained in:
parent
15a5b347e8
commit
5b2810e6c5
@ -578,7 +578,11 @@ print("run[CQ:image,file="+j["img"]+"]")
|
|||||||
|
|
||||||
- [x] 团队猜歌
|
- [x] 团队猜歌
|
||||||
|
|
||||||
- [x] 设置缓存歌库路径 [绝对路径]
|
- [x] 设置猜歌缓存歌库路径 [绝对路径]
|
||||||
|
|
||||||
|
- [x] 设置猜歌本地 [true/false]
|
||||||
|
|
||||||
|
- [x] 设置猜歌Api [true/false]
|
||||||
|
|
||||||
- 注:默认歌库为网易云热歌榜
|
- 注:默认歌库为网易云热歌榜
|
||||||
|
|
||||||
|
|||||||
@ -3,9 +3,12 @@ package guessmusic
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -17,13 +20,10 @@ import (
|
|||||||
"github.com/wdvxdr1123/ZeroBot/message"
|
"github.com/wdvxdr1123/ZeroBot/message"
|
||||||
|
|
||||||
ctrl "github.com/FloatTech/zbpctrl"
|
ctrl "github.com/FloatTech/zbpctrl"
|
||||||
"github.com/FloatTech/zbputils/binary"
|
"github.com/FloatTech/zbputils/control"
|
||||||
control "github.com/FloatTech/zbputils/control"
|
|
||||||
"github.com/FloatTech/zbputils/ctxext"
|
"github.com/FloatTech/zbputils/ctxext"
|
||||||
"github.com/FloatTech/zbputils/file"
|
"github.com/FloatTech/zbputils/file"
|
||||||
"github.com/FloatTech/zbputils/web"
|
"github.com/FloatTech/zbputils/web"
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
"github.com/wdvxdr1123/ZeroBot/extension/single"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,8 +32,12 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
musicPath = file.BOTPATH + "/data/guessmusic/music/" // 绝对路径,歌库根目录,通过指令进行更改
|
cuttime = [...]string{"00:00:05", "00:00:30", "00:01:00"} // 音乐切割时间点,可自行调节时间(时:分:秒)
|
||||||
cuttime = [...]string{"00:00:05", "00:00:30", "00:01:00"} // 音乐切割时间点,可自行调节时间(时:分:秒)
|
cfg = config{ // 默认 config
|
||||||
|
MusicPath: file.BOTPATH + "/data/guessmusic/music/", // 绝对路径,歌库根目录,通过指令进行更改
|
||||||
|
Local: true, // 是否使用本地音乐库
|
||||||
|
API: true, // 是否使用 Api
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() { // 插件主体
|
func init() { // 插件主体
|
||||||
@ -42,7 +46,9 @@ func init() { // 插件主体
|
|||||||
Help: "猜歌插件(该插件依赖ffmpeg)\n" +
|
Help: "猜歌插件(该插件依赖ffmpeg)\n" +
|
||||||
"- 个人猜歌\n" +
|
"- 个人猜歌\n" +
|
||||||
"- 团队猜歌\n" +
|
"- 团队猜歌\n" +
|
||||||
"- 设置缓存歌库路径 [绝对路径]\n" +
|
"- 设置猜歌缓存歌库路径 [绝对路径]\n" +
|
||||||
|
"- 设置猜歌本地 [true/false]\n" +
|
||||||
|
"- 设置猜歌Api [true/false]\n" +
|
||||||
"注:默认歌库为网易云热歌榜\n" +
|
"注:默认歌库为网易云热歌榜\n" +
|
||||||
"1.可在后面添加“-动漫”进行动漫歌猜歌\n-这个只能猜歌名和歌手\n" +
|
"1.可在后面添加“-动漫”进行动漫歌猜歌\n-这个只能猜歌名和歌手\n" +
|
||||||
"2.可在后面添加“-动漫2”进行动漫歌猜歌\n-这个可以猜番名,但歌手经常“未知”",
|
"2.可在后面添加“-动漫2”进行动漫歌猜歌\n-这个可以猜番名,但歌手经常“未知”",
|
||||||
@ -62,15 +68,28 @@ func init() { // 插件主体
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
cfgfile := engine.DataFolder() + "setpath.txt"
|
cfgFile := engine.DataFolder() + "config.json"
|
||||||
if file.IsExist(cfgfile) {
|
if file.IsExist(cfgFile) {
|
||||||
b, err := os.ReadFile(cfgfile)
|
reader, err := os.Open(cfgFile)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
musicPath = binary.BytesToString(b)
|
err = json.NewDecoder(reader).Decode(&cfg)
|
||||||
logrus.Infoln("[guessmusic] set dir to", musicPath)
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = reader.Close()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = saveConfig(cfgFile)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
engine.OnRegex(`^设置缓存歌库路径(.*)$`, func(ctx *zero.Ctx) bool {
|
engine.OnRegex(`^设置猜歌(缓存歌库路径|本地|Api)\s*(.*)$`, func(ctx *zero.Ctx) bool {
|
||||||
if !zero.SuperUserPermission(ctx) {
|
if !zero.SuperUserPermission(ctx) {
|
||||||
ctx.SendChain(message.Text("只有bot主人可以设置!"))
|
ctx.SendChain(message.Text("只有bot主人可以设置!"))
|
||||||
return false
|
return false
|
||||||
@ -78,15 +97,35 @@ func init() { // 插件主体
|
|||||||
return true
|
return true
|
||||||
}).SetBlock(true).
|
}).SetBlock(true).
|
||||||
Handle(func(ctx *zero.Ctx) {
|
Handle(func(ctx *zero.Ctx) {
|
||||||
musicPath = ctx.State["regex_matched"].([]string)[1]
|
option := ctx.State["regex_matched"].([]string)[1]
|
||||||
if musicPath == "" {
|
value := ctx.State["regex_matched"].([]string)[2]
|
||||||
ctx.SendChain(message.Text("请输入正确的路径!"))
|
switch option {
|
||||||
|
case "缓存歌库路径":
|
||||||
|
if value == "" {
|
||||||
|
ctx.SendChain(message.Text("请输入正确的路径!"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
musicPath := strings.ReplaceAll(value, "\\", "/")
|
||||||
|
if !strings.HasSuffix(musicPath, "/") {
|
||||||
|
musicPath += "/"
|
||||||
|
}
|
||||||
|
cfg.MusicPath = musicPath
|
||||||
|
case "本地":
|
||||||
|
choice, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cfg.Local = choice
|
||||||
|
case "Api":
|
||||||
|
choice, err := strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
ctx.SendChain(message.Text("ERROR:", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cfg.API = choice
|
||||||
}
|
}
|
||||||
musicPath = strings.ReplaceAll(musicPath, "\\", "/")
|
err = saveConfig(cfgFile)
|
||||||
if !strings.HasSuffix(musicPath, "/") {
|
|
||||||
musicPath += "/"
|
|
||||||
}
|
|
||||||
err := os.WriteFile(cfgfile, binary.StringToBytes(musicPath), 0644)
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ctx.SendChain(message.Text("成功!"))
|
ctx.SendChain(message.Text("成功!"))
|
||||||
} else {
|
} else {
|
||||||
@ -103,29 +142,29 @@ func init() { // 插件主体
|
|||||||
ctx.SendChain(message.Text("正在准备歌曲,请稍等\n回答“-[歌曲名称|歌手|提示|取消]”\n一共3段语音,6次机会"))
|
ctx.SendChain(message.Text("正在准备歌曲,请稍等\n回答“-[歌曲名称|歌手|提示|取消]”\n一共3段语音,6次机会"))
|
||||||
}
|
}
|
||||||
// 随机抽歌
|
// 随机抽歌
|
||||||
musicname, pathofmusic, err := musiclottery(mode, musicPath)
|
musicName, pathOfMusic, err := musicLottery(mode, cfg.MusicPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text(err))
|
ctx.SendChain(message.Text(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 切割音频,生成3个10秒的音频
|
// 切割音频,生成3个10秒的音频
|
||||||
outputPath := cachePath + gid + "/"
|
outputPath := cachePath + gid + "/"
|
||||||
err = musiccut(musicname, pathofmusic, outputPath)
|
err = cutMusic(musicName, pathOfMusic, outputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.SendChain(message.Text(err))
|
ctx.SendChain(message.Text(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 进行猜歌环节
|
// 进行猜歌环节
|
||||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + "0.wav"))
|
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + "0.wav"))
|
||||||
answerstring := strings.Split(musicname, " - ")
|
answerString := strings.Split(musicName, " - ")
|
||||||
var next *zero.FutureEvent
|
var next *zero.FutureEvent
|
||||||
if ctx.State["regex_matched"].([]string)[1] == "个人" {
|
if ctx.State["regex_matched"].([]string)[1] == "个人" {
|
||||||
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), ctx.CheckSession())
|
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), ctx.CheckSession())
|
||||||
} else {
|
} else {
|
||||||
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), zero.CheckGroup(ctx.Event.GroupID))
|
next = zero.NewFutureEvent("message", 999, false, zero.OnlyGroup, zero.RegexRule(`^-\S{1,}`), zero.CheckGroup(ctx.Event.GroupID))
|
||||||
}
|
}
|
||||||
var countofmusic = 0 // 音频数量
|
var musicCount = 0 // 音频数量
|
||||||
var countofanswer = 0 // 问答次数
|
var answerCount = 0 // 问答次数
|
||||||
recv, cancel := next.Repeat()
|
recv, cancel := next.Repeat()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
wait := time.NewTimer(40 * time.Second)
|
wait := time.NewTimer(40 * time.Second)
|
||||||
@ -139,24 +178,24 @@ func init() { // 插件主体
|
|||||||
msg := make(message.Message, 0, 3)
|
msg := make(message.Message, 0, 3)
|
||||||
msg = append(msg, message.Reply(ctx.Event.MessageID))
|
msg = append(msg, message.Reply(ctx.Event.MessageID))
|
||||||
msg = append(msg, message.Text("猜歌超时,游戏结束\n答案是:",
|
msg = append(msg, message.Text("猜歌超时,游戏结束\n答案是:",
|
||||||
"\n歌名:", answerstring[0],
|
"\n歌名:", answerString[0],
|
||||||
"\n歌手:", answerstring[1]))
|
"\n歌手:", answerString[1]))
|
||||||
if mode == "-动漫2" {
|
if mode == "-动漫2" {
|
||||||
msg = append(msg, message.Text("\n歌曲出自:", answerstring[2]))
|
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||||
}
|
}
|
||||||
ctx.Send(msg)
|
ctx.Send(msg)
|
||||||
return
|
return
|
||||||
case <-wait.C:
|
case <-wait.C:
|
||||||
wait.Reset(40 * time.Second)
|
wait.Reset(40 * time.Second)
|
||||||
countofmusic++
|
musicCount++
|
||||||
if countofmusic > 2 {
|
if musicCount > 2 {
|
||||||
wait.Stop()
|
wait.Stop()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ctx.SendChain(
|
ctx.SendChain(
|
||||||
message.Text("好像有些难度呢,再听这段音频,要仔细听哦"),
|
message.Text("好像有些难度呢,再听这段音频,要仔细听哦"),
|
||||||
)
|
)
|
||||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(countofmusic) + ".wav"))
|
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
|
||||||
case c := <-recv:
|
case c := <-recv:
|
||||||
wait.Reset(40 * time.Second)
|
wait.Reset(40 * time.Second)
|
||||||
tick.Reset(105 * time.Second)
|
tick.Reset(105 * time.Second)
|
||||||
@ -171,10 +210,10 @@ func init() { // 插件主体
|
|||||||
msg := make(message.Message, 0, 3)
|
msg := make(message.Message, 0, 3)
|
||||||
msg = append(msg, message.Reply(c.Event.MessageID))
|
msg = append(msg, message.Reply(c.Event.MessageID))
|
||||||
msg = append(msg, message.Text("游戏已取消,猜歌答案是",
|
msg = append(msg, message.Text("游戏已取消,猜歌答案是",
|
||||||
"\n歌名:", answerstring[0],
|
"\n歌名:", answerString[0],
|
||||||
"\n歌手:", answerstring[1]))
|
"\n歌手:", answerString[1]))
|
||||||
if mode == "-动漫2" {
|
if mode == "-动漫2" {
|
||||||
msg = append(msg, message.Text("\n歌曲出自:", answerstring[2]))
|
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||||
}
|
}
|
||||||
ctx.Send(msg)
|
ctx.Send(msg)
|
||||||
return
|
return
|
||||||
@ -185,8 +224,8 @@ func init() { // 插件主体
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
case answer == "提示":
|
case answer == "提示":
|
||||||
countofmusic++
|
musicCount++
|
||||||
if countofmusic > 2 {
|
if musicCount > 2 {
|
||||||
wait.Stop()
|
wait.Stop()
|
||||||
ctx.Send(
|
ctx.Send(
|
||||||
message.ReplyWithMessage(c.Event.MessageID,
|
message.ReplyWithMessage(c.Event.MessageID,
|
||||||
@ -201,87 +240,87 @@ func init() { // 插件主体
|
|||||||
message.Text("再听这段音频,要仔细听哦"),
|
message.Text("再听这段音频,要仔细听哦"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(countofmusic) + ".wav"))
|
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
|
||||||
case strings.Contains(answerstring[0], answer) || strings.EqualFold(answerstring[0], answer):
|
case strings.Contains(answerString[0], answer) || strings.EqualFold(answerString[0], answer):
|
||||||
wait.Stop()
|
wait.Stop()
|
||||||
tick.Stop()
|
tick.Stop()
|
||||||
after.Stop()
|
after.Stop()
|
||||||
msg := make(message.Message, 0, 3)
|
msg := make(message.Message, 0, 3)
|
||||||
msg = append(msg, message.Reply(c.Event.MessageID))
|
msg = append(msg, message.Reply(c.Event.MessageID))
|
||||||
msg = append(msg, message.Text("太棒了,你猜对歌曲名了!答案是",
|
msg = append(msg, message.Text("太棒了,你猜对歌曲名了!答案是",
|
||||||
"\n歌名:", answerstring[0],
|
"\n歌名:", answerString[0],
|
||||||
"\n歌手:", answerstring[1]))
|
"\n歌手:", answerString[1]))
|
||||||
if mode == "-动漫2" {
|
if mode == "-动漫2" {
|
||||||
msg = append(msg, message.Text("\n歌曲出自:", answerstring[2]))
|
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||||
}
|
}
|
||||||
ctx.Send(msg)
|
ctx.Send(msg)
|
||||||
return
|
return
|
||||||
case answerstring[1] == "未知" && answer == "未知":
|
case answerString[1] == "未知" && answer == "未知":
|
||||||
ctx.Send(
|
ctx.Send(
|
||||||
message.ReplyWithMessage(c.Event.MessageID,
|
message.ReplyWithMessage(c.Event.MessageID,
|
||||||
message.Text("该模式禁止回答“未知”"),
|
message.Text("该模式禁止回答“未知”"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
case strings.Contains(answerstring[1], answer) || strings.EqualFold(answerstring[1], answer):
|
case strings.Contains(answerString[1], answer) || strings.EqualFold(answerString[1], answer):
|
||||||
wait.Stop()
|
wait.Stop()
|
||||||
tick.Stop()
|
tick.Stop()
|
||||||
after.Stop()
|
after.Stop()
|
||||||
msg := make(message.Message, 0, 3)
|
msg := make(message.Message, 0, 3)
|
||||||
msg = append(msg, message.Reply(c.Event.MessageID))
|
msg = append(msg, message.Reply(c.Event.MessageID))
|
||||||
msg = append(msg, message.Text("太棒了,你猜对歌手名了!答案是",
|
msg = append(msg, message.Text("太棒了,你猜对歌手名了!答案是",
|
||||||
"\n歌名:", answerstring[0],
|
"\n歌名:", answerString[0],
|
||||||
"\n歌手:", answerstring[1]))
|
"\n歌手:", answerString[1]))
|
||||||
if mode == "-动漫2" {
|
if mode == "-动漫2" {
|
||||||
msg = append(msg, message.Text("\n歌曲出自:", answerstring[2]))
|
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||||
}
|
}
|
||||||
ctx.Send(msg)
|
ctx.Send(msg)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
if mode == "-动漫2" && (strings.Contains(answerstring[2], answer) || strings.EqualFold(answerstring[2], answer)) {
|
if mode == "-动漫2" && (strings.Contains(answerString[2], answer) || strings.EqualFold(answerString[2], answer)) {
|
||||||
wait.Stop()
|
wait.Stop()
|
||||||
tick.Stop()
|
tick.Stop()
|
||||||
after.Stop()
|
after.Stop()
|
||||||
ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
ctx.Send(message.ReplyWithMessage(c.Event.MessageID,
|
||||||
message.Text("太棒了,你猜对番剧名了!答案是:",
|
message.Text("太棒了,你猜对番剧名了!答案是:",
|
||||||
"\n歌名:", answerstring[0],
|
"\n歌名:", answerString[0],
|
||||||
"\n歌手:", answerstring[1],
|
"\n歌手:", answerString[1],
|
||||||
"\n歌曲出自:", answerstring[2]),
|
"\n歌曲出自:", answerString[2]),
|
||||||
))
|
))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
countofmusic++
|
musicCount++
|
||||||
switch {
|
switch {
|
||||||
case countofmusic > 2 && countofanswer < 6:
|
case musicCount > 2 && answerCount < 6:
|
||||||
wait.Stop()
|
wait.Stop()
|
||||||
countofanswer++
|
answerCount++
|
||||||
ctx.Send(
|
ctx.Send(
|
||||||
message.ReplyWithMessage(c.Event.MessageID,
|
message.ReplyWithMessage(c.Event.MessageID,
|
||||||
message.Text("答案不对哦,加油啊~"),
|
message.Text("答案不对哦,加油啊~"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
case countofmusic > 2:
|
case musicCount > 2:
|
||||||
wait.Stop()
|
wait.Stop()
|
||||||
tick.Stop()
|
tick.Stop()
|
||||||
after.Stop()
|
after.Stop()
|
||||||
msg := make(message.Message, 0, 3)
|
msg := make(message.Message, 0, 3)
|
||||||
msg = append(msg, message.Reply(c.Event.MessageID))
|
msg = append(msg, message.Reply(c.Event.MessageID))
|
||||||
msg = append(msg, message.Text("次数到了,你没能猜出来。\n答案是:",
|
msg = append(msg, message.Text("次数到了,你没能猜出来。\n答案是:",
|
||||||
"\n歌名:", answerstring[0],
|
"\n歌名:", answerString[0],
|
||||||
"\n歌手:", answerstring[1]))
|
"\n歌手:", answerString[1]))
|
||||||
if mode == "-动漫2" {
|
if mode == "-动漫2" {
|
||||||
msg = append(msg, message.Text("\n歌曲出自:", answerstring[2]))
|
msg = append(msg, message.Text("\n歌曲出自:", answerString[2]))
|
||||||
}
|
}
|
||||||
ctx.Send(msg)
|
ctx.Send(msg)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
wait.Reset(40 * time.Second)
|
wait.Reset(40 * time.Second)
|
||||||
countofanswer++
|
answerCount++
|
||||||
ctx.Send(
|
ctx.Send(
|
||||||
message.ReplyWithMessage(c.Event.MessageID,
|
message.ReplyWithMessage(c.Event.MessageID,
|
||||||
message.Text("答案不对,再听这段音频,要仔细听哦"),
|
message.Text("答案不对,再听这段音频,要仔细听哦"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(countofmusic) + ".wav"))
|
ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + strconv.Itoa(musicCount) + ".wav"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,99 +328,139 @@ func init() { // 插件主体
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func saveConfig(cfgFile string) (err error) {
|
||||||
|
if reader, err := os.OpenFile(cfgFile, os.O_CREATE, os.ModePerm); err == nil {
|
||||||
|
err = json.NewEncoder(reader).Encode(&cfg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// 随机抽取音乐
|
// 随机抽取音乐
|
||||||
func musiclottery(mode, musicPath string) (musicname, pathofmusic string, err error) {
|
func musicLottery(mode, musicPath string) (musicName, pathOfMusic string, err error) {
|
||||||
switch mode {
|
switch mode {
|
||||||
case "-动漫":
|
case "-动漫":
|
||||||
pathofmusic = musicPath + "动漫/"
|
pathOfMusic = musicPath + "动漫/"
|
||||||
case "-动漫2":
|
case "-动漫2":
|
||||||
pathofmusic = musicPath + "动漫2/"
|
pathOfMusic = musicPath + "动漫2/"
|
||||||
default:
|
default:
|
||||||
pathofmusic = musicPath + "歌榜/"
|
pathOfMusic = musicPath + "歌榜/"
|
||||||
}
|
}
|
||||||
err = os.MkdirAll(pathofmusic, 0755)
|
err = os.MkdirAll(pathOfMusic, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Errorf("[生成文件夹错误]ERROR:%s", err)
|
err = errors.Errorf("[生成文件夹错误]ERROR:%s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
files, err := ioutil.ReadDir(pathofmusic)
|
files, err := ioutil.ReadDir(pathOfMusic)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Errorf("[读取本地列表错误]ERROR:%s", err)
|
err = errors.Errorf("[读取本地列表错误]ERROR:%s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 随机抽取音乐从本地或者线上
|
|
||||||
switch {
|
if cfg.Local && cfg.API {
|
||||||
case len(files) == 0:
|
switch {
|
||||||
// 如果没有任何本地就下载歌曲
|
case len(files) == 0:
|
||||||
switch mode {
|
// 如果没有任何本地就下载歌曲
|
||||||
case "-动漫":
|
musicName, err = getAPIMusic(mode, pathOfMusic)
|
||||||
musicname, err = getpaugramdata(pathofmusic)
|
if err != nil {
|
||||||
case "-动漫2":
|
err = errors.Errorf("[本地数据为0,歌曲下载错误]ERROR:%s", err)
|
||||||
musicname, err = getanimedata(pathofmusic)
|
return
|
||||||
|
}
|
||||||
|
case rand.Intn(2) == 0:
|
||||||
|
// [0,1)只会取到0,rand不允许的
|
||||||
|
musicName = getLocalMusic(files)
|
||||||
default:
|
default:
|
||||||
musicname, err = getuomgdata(pathofmusic)
|
musicName, err = getAPIMusic(mode, pathOfMusic)
|
||||||
|
if err != nil {
|
||||||
|
// 如果下载失败就从本地抽一个歌曲
|
||||||
|
musicName = getLocalMusic(files)
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
return
|
||||||
err = errors.Errorf("[本地数据为0,歌曲下载错误]ERROR:%s", err)
|
}
|
||||||
|
if cfg.Local {
|
||||||
|
if len(files) == 0 {
|
||||||
|
err = errors.New("[本地数据为0,未开启API数据]")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case rand.Intn(2) == 0:
|
musicName = getLocalMusic(files)
|
||||||
// [0,1)只会取到0,rand不允许的
|
return
|
||||||
if len(files) > 1 {
|
}
|
||||||
musicname = strings.Replace(files[rand.Intn(len(files))].Name(), ".mp3", "", 1)
|
if cfg.API {
|
||||||
} else {
|
musicName, err = getAPIMusic(mode, pathOfMusic)
|
||||||
musicname = strings.Replace(files[0].Name(), ".mp3", "", 1)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
switch mode {
|
|
||||||
case "-动漫":
|
|
||||||
musicname, err = getpaugramdata(pathofmusic)
|
|
||||||
case "-动漫2":
|
|
||||||
musicname, err = getanimedata(pathofmusic)
|
|
||||||
default:
|
|
||||||
musicname, err = getuomgdata(pathofmusic)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// 如果下载失败就从本地抽一个歌曲
|
err = errors.Errorf("[获取API失败,未开启本地数据] ERROR:%s", err)
|
||||||
if len(files) > 1 {
|
return
|
||||||
musicname = strings.Replace(files[rand.Intn(len(files))].Name(), ".mp3", "", 1)
|
|
||||||
} else {
|
|
||||||
musicname = strings.Replace(files[0].Name(), ".mp3", "", 1)
|
|
||||||
}
|
|
||||||
err = nil
|
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = errors.New("[未开启API以及本地数据]")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAPIMusic(mode string, musicPath string) (musicName string, err error) {
|
||||||
|
switch mode {
|
||||||
|
case "-动漫":
|
||||||
|
musicName, err = getPaugramData(musicPath)
|
||||||
|
case "-动漫2":
|
||||||
|
musicName, err = getAnimeData(musicPath)
|
||||||
|
default:
|
||||||
|
musicName, err = getNetEaseData(musicPath)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLocalMusic(files []fs.FileInfo) (musicName string) {
|
||||||
|
if len(files) > 1 {
|
||||||
|
musicName = strings.Replace(files[rand.Intn(len(files))].Name(), ".mp3", "", 1)
|
||||||
|
} else {
|
||||||
|
musicName = strings.Replace(files[0].Name(), ".mp3", "", 1)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下载保罗API的歌曲
|
// 下载保罗API的歌曲
|
||||||
func getpaugramdata(musicPath string) (musicname string, err error) {
|
func getPaugramData(musicPath string) (musicName string, err error) {
|
||||||
api := "https://api.paugram.com/acgm/?list=1"
|
api := "https://api.paugram.com/acgm/?list=1"
|
||||||
referer := "https://api.paugram.com/"
|
referer := "https://api.paugram.com/"
|
||||||
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
|
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
name := gjson.Get(binary.BytesToString(data), "title").String()
|
var parsed paugramData
|
||||||
artistsname := gjson.Get(binary.BytesToString(data), "artist").String()
|
err = json.Unmarshal(data, &parsed)
|
||||||
musicurl := gjson.Get(binary.BytesToString(data), "link").String()
|
if err != nil {
|
||||||
if name == "" || artistsname == "" {
|
|
||||||
err = errors.Errorf("the music is missed")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
musicname = name + " - " + artistsname
|
name := parsed.Title
|
||||||
downmusic := musicPath + "/" + musicname + ".mp3"
|
artistsName := parsed.Artist
|
||||||
response, err := http.Head(musicurl)
|
musicURL := parsed.Link
|
||||||
if err != nil || response.StatusCode != 200 {
|
if name == "" || artistsName == "" {
|
||||||
err = errors.Errorf("the music is missed")
|
err = errors.New("无法获API取歌曲信息")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if file.IsNotExist(downmusic) {
|
musicName = name + " - " + artistsName
|
||||||
data, err = web.GetData(musicurl + ".mp3")
|
downMusic := musicPath + "/" + musicName + ".mp3"
|
||||||
|
response, err := http.Head(musicURL)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Errorf("下载音乐失败, ERROR: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
err = errors.Errorf("下载音乐失败, Status Code: %d", response.StatusCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if file.IsNotExist(downMusic) {
|
||||||
|
data, err = web.GetData(musicURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = os.WriteFile(downmusic, data, 0666)
|
err = os.WriteFile(downMusic, data, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -390,34 +469,66 @@ func getpaugramdata(musicPath string) (musicname string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 下载animeMusic API的歌曲
|
// 下载animeMusic API的歌曲
|
||||||
func getanimedata(musicPath string) (musicname string, err error) {
|
func getAnimeData(musicPath string) (musicName string, err error) {
|
||||||
api := "https://anime-music.jijidown.com/api/v2/music"
|
api := "https://anime-music.jijidown.com/api/v2/music"
|
||||||
referer := "https://anime-music.jijidown.com/"
|
referer := "https://anime-music.jijidown.com/"
|
||||||
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
|
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
name := gjson.Get(binary.BytesToString(data), "res").Get("title").String()
|
var parsed animeData
|
||||||
artistsname := gjson.Get(binary.BytesToString(data), "res").Get("author").String()
|
err = json.Unmarshal(data, &parsed)
|
||||||
acgname := gjson.Get(binary.BytesToString(data), "res").Get("anime_info").Get("title").String()
|
if err != nil {
|
||||||
musicurl := gjson.Get(binary.BytesToString(data), "res").Get("play_url").String()
|
|
||||||
if name == "" || artistsname == "" {
|
|
||||||
err = errors.Errorf("the music is missed")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
musicname = name + " - " + artistsname + " - " + acgname
|
name := parsed.Res.Title
|
||||||
downmusic := musicPath + "/" + musicname + ".mp3"
|
artistName := parsed.Res.Author
|
||||||
response, err := http.Head(musicurl)
|
acgName := parsed.Res.AnimeInfo.Title
|
||||||
if err != nil || response.StatusCode != 200 {
|
//musicURL := parsed.Res.PlayURL
|
||||||
err = errors.Errorf("the music is missed")
|
if name == "" || artistName == "" {
|
||||||
|
err = errors.New("无法获API取歌曲信息")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if file.IsNotExist(downmusic) {
|
requestURL := "https://autumnfish.cn/search?keywords=" + url.QueryEscape(name+" "+artistName) + "&limit=1"
|
||||||
data, err = web.GetData(musicurl + ".mp3")
|
if artistName == "未知" {
|
||||||
|
requestURL = "https://autumnfish.cn/search?keywords=" + url.QueryEscape(acgName+" "+name) + "&limit=1"
|
||||||
|
}
|
||||||
|
data, err = web.GetData(requestURL)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Errorf("API歌曲查询失败, ERROR: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var autumnfish autumnfishData
|
||||||
|
err = json.Unmarshal(data, &autumnfish)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if autumnfish.Code != 200 {
|
||||||
|
err = errors.Errorf("下载音乐失败, Status Code: %d", autumnfish.Code)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
musicID := strconv.Itoa(autumnfish.Result.Songs[0].ID)
|
||||||
|
if artistName == "未知" {
|
||||||
|
artistName = strings.ReplaceAll(autumnfish.Result.Songs[0].Artists[0].Name, " - ", "-")
|
||||||
|
}
|
||||||
|
musicName = name + " - " + artistName + " - " + acgName
|
||||||
|
downMusic := musicPath + "/" + musicName + ".mp3"
|
||||||
|
musicURL := "http://music.163.com/song/media/outer/url?id=" + musicID
|
||||||
|
response, err := http.Head(musicURL)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.Errorf("下载音乐失败, ERROR: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
err = errors.Errorf("下载音乐失败, Status Code: %d", response.StatusCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if file.IsNotExist(downMusic) {
|
||||||
|
data, err = web.GetData(musicURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = os.WriteFile(downmusic, data, 0666)
|
err = os.WriteFile(downMusic, data, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -426,25 +537,33 @@ func getanimedata(musicPath string) (musicname string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 下载网易云热歌榜音乐
|
// 下载网易云热歌榜音乐
|
||||||
func getuomgdata(musicPath string) (musicname string, err error) {
|
func getNetEaseData(musicPath string) (musicName string, err error) {
|
||||||
api := "https://api.uomg.com/api/rand.music?sort=%E7%83%AD%E6%AD%8C%E6%A6%9C&format=json"
|
api := "https://api.uomg.com/api/rand.music?sort=%E7%83%AD%E6%AD%8C%E6%A6%9C&format=json"
|
||||||
referer := "https://api.uomg.com/api/rand.music"
|
referer := "https://api.uomg.com/api/rand.music"
|
||||||
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
|
data, err := web.RequestDataWith(web.NewDefaultClient(), api, "GET", referer, ua)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
musicdata := gjson.Get(binary.BytesToString(data), "data")
|
var parsed netEaseData
|
||||||
name := musicdata.Get("name").String()
|
err = json.Unmarshal(data, &parsed)
|
||||||
musicurl := musicdata.Get("url").String()
|
if err != nil {
|
||||||
artistsname := musicdata.Get("artistsname").String()
|
return
|
||||||
musicname = name + " - " + artistsname
|
}
|
||||||
downmusic := musicPath + "/" + musicname + ".mp3"
|
name := parsed.Data.Name
|
||||||
if file.IsNotExist(downmusic) {
|
musicURL := parsed.Data.URL
|
||||||
data, err = web.GetData(musicurl + ".mp3")
|
artistsName := parsed.Data.Artistsname
|
||||||
|
if name == "" || artistsName == "" {
|
||||||
|
err = errors.New("无法获API取歌曲信息")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
musicName = name + " - " + artistsName
|
||||||
|
downMusic := musicPath + "/" + musicName + ".mp3"
|
||||||
|
if file.IsNotExist(downMusic) {
|
||||||
|
data, err = web.GetData(musicURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = os.WriteFile(downmusic, data, 0666)
|
err = os.WriteFile(downMusic, data, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -453,14 +572,14 @@ func getuomgdata(musicPath string) (musicname string, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 切割音乐成三个10s音频
|
// 切割音乐成三个10s音频
|
||||||
func musiccut(musicname, pathofmusic, outputPath string) (err error) {
|
func cutMusic(musicName, pathOfMusic, outputPath string) (err error) {
|
||||||
err = os.MkdirAll(outputPath, 0755)
|
err = os.MkdirAll(outputPath, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Errorf("[生成歌曲目录错误]ERROR:%s", err)
|
err = errors.Errorf("[生成歌曲目录错误]ERROR:%s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var stderr bytes.Buffer
|
var stderr bytes.Buffer
|
||||||
cmdArguments := []string{"-y", "-i", pathofmusic + musicname + ".mp3",
|
cmdArguments := []string{"-y", "-i", pathOfMusic + musicName + ".mp3",
|
||||||
"-ss", cuttime[0], "-t", "10", file.BOTPATH + "/" + outputPath + "0.wav",
|
"-ss", cuttime[0], "-t", "10", file.BOTPATH + "/" + outputPath + "0.wav",
|
||||||
"-ss", cuttime[1], "-t", "10", file.BOTPATH + "/" + outputPath + "1.wav",
|
"-ss", cuttime[1], "-t", "10", file.BOTPATH + "/" + outputPath + "1.wav",
|
||||||
"-ss", cuttime[2], "-t", "10", file.BOTPATH + "/" + outputPath + "2.wav", "-hide_banner"}
|
"-ss", cuttime[2], "-t", "10", file.BOTPATH + "/" + outputPath + "2.wav", "-hide_banner"}
|
||||||
|
|||||||
107
plugin/guessmusic/struct.go
Normal file
107
plugin/guessmusic/struct.go
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
package guessmusic
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
MusicPath string `json:"musicPath"`
|
||||||
|
Local bool `json:"local"`
|
||||||
|
API bool `json:"api"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type paugramData struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Artist string `json:"artist"`
|
||||||
|
Album string `json:"album"`
|
||||||
|
Cover string `json:"cover"`
|
||||||
|
Lyric string `json:"lyric"`
|
||||||
|
SubLyric string `json:"sub_lyric"`
|
||||||
|
Link string `json:"link"`
|
||||||
|
Cached bool `json:"cached"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type animeData struct {
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
Res struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
AnimeInfo struct {
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
Atime int `json:"atime"`
|
||||||
|
Logo string `json:"logo"`
|
||||||
|
Year int `json:"year"`
|
||||||
|
Bg string `json:"bg"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Month int `json:"month"`
|
||||||
|
} `json:"anime_info"`
|
||||||
|
PlayURL string `json:"play_url"`
|
||||||
|
Atime int `json:"atime"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Author string `json:"author"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Recommend bool `json:"recommend"`
|
||||||
|
} `json:"res"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type netEaseData struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Data struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
URL string `json:"url"`
|
||||||
|
Picurl string `json:"picurl"`
|
||||||
|
Artistsname string `json:"artistsname"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type autumnfishData struct {
|
||||||
|
Result struct {
|
||||||
|
Songs []struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Artists []struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
PicURL interface{} `json:"picUrl"`
|
||||||
|
Alias []interface{} `json:"alias"`
|
||||||
|
AlbumSize int `json:"albumSize"`
|
||||||
|
PicID int `json:"picId"`
|
||||||
|
Img1V1URL string `json:"img1v1Url"`
|
||||||
|
Img1V1 int `json:"img1v1"`
|
||||||
|
Trans interface{} `json:"trans"`
|
||||||
|
} `json:"artists"`
|
||||||
|
Album struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Artist struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
PicURL interface{} `json:"picUrl"`
|
||||||
|
Alias []interface{} `json:"alias"`
|
||||||
|
AlbumSize int `json:"albumSize"`
|
||||||
|
PicID int `json:"picId"`
|
||||||
|
Img1V1URL string `json:"img1v1Url"`
|
||||||
|
Img1V1 int `json:"img1v1"`
|
||||||
|
Trans interface{} `json:"trans"`
|
||||||
|
} `json:"artist"`
|
||||||
|
PublishTime int64 `json:"publishTime"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
CopyrightID int `json:"copyrightId"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
PicID int64 `json:"picId"`
|
||||||
|
Mark int `json:"mark"`
|
||||||
|
} `json:"album"`
|
||||||
|
Duration int `json:"duration"`
|
||||||
|
CopyrightID int `json:"copyrightId"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
Alias []interface{} `json:"alias"`
|
||||||
|
Rtype int `json:"rtype"`
|
||||||
|
Ftype int `json:"ftype"`
|
||||||
|
Mvid int `json:"mvid"`
|
||||||
|
Fee int `json:"fee"`
|
||||||
|
RURL interface{} `json:"rUrl"`
|
||||||
|
Mark int `json:"mark"`
|
||||||
|
} `json:"songs"`
|
||||||
|
HasMore bool `json:"hasMore"`
|
||||||
|
SongCount int `json:"songCount"`
|
||||||
|
} `json:"result"`
|
||||||
|
Code int `json:"code"`
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user