ZeroBot-Plugin/plugin/music/selecter.go
2026-01-23 16:53:55 +08:00

202 lines
5.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package music 整合多平台音乐点播能力
package music
import (
"fmt"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
"github.com/FloatTech/zbputils/ctxext"
"github.com/guohuiyuan/music-lib/kugou"
"github.com/guohuiyuan/music-lib/kuwo"
"github.com/guohuiyuan/music-lib/migu"
"github.com/guohuiyuan/music-lib/netease"
"github.com/guohuiyuan/music-lib/qq"
"github.com/pkg/errors"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
)
var platformMap = map[string]func(string) (message.Segment, error){
"咪咕": getMiguMusic,
"酷我": getKuwoMusic,
"酷狗": getKugouMusic,
"网易": getNeteaseMusic,
"qq": getQQMusic,
"": getKuwoMusic, // 默认点歌指向酷我
}
func init() {
control.AutoRegister(&ctrl.Options[*zero.Ctx]{
DisableOnDefault: false,
Brief: "点歌",
Help: "- 点歌[xxx] (默认酷我)\n" +
"- 网易点歌[xxx]\n" +
"- 酷我点歌[xxx]\n" +
"- 酷狗点歌[xxx]\n" +
"- 咪咕点歌[xxx]\n" +
"- qq点歌[xxx]\n",
}).OnRegex(`^(.{0,2})点歌\s?(.{1,25})$`).SetBlock(true).Limit(ctxext.LimitByUser).
Handle(func(ctx *zero.Ctx) {
matches := ctx.State["regex_matched"].([]string)
platformPrefix := matches[1]
keyword := matches[2]
processFunc, ok := platformMap[platformPrefix]
if !ok {
ctx.SendChain(message.Text("不支持的点播平台:", platformPrefix))
return
}
seg, err := processFunc(keyword)
if err != nil {
ctx.SendChain(message.Text("点歌失败:", err))
return
}
ctx.SendChain(seg)
})
}
// getMusicSegment 根据平台和关键词获取音乐消息段
func getMusicSegment(platform, keyword string) (message.Segment, error) {
switch platform {
case "migu":
return getMiguMusic(keyword)
case "kuwo":
return getKuwoMusic(keyword)
case "kugou":
return getKugouMusic(keyword)
case "netease":
return getNeteaseMusic(keyword)
case "qq":
return getQQMusic(keyword)
default:
return message.Segment{}, errors.New("未知的音乐平台:" + platform)
}
}
func getMiguMusic(keyword string) (message.Segment, error) {
songs, err := migu.Search(keyword)
if err != nil {
return message.Segment{}, errors.Wrap(err, "咪咕音乐搜索失败")
}
if len(songs) == 0 {
return message.Segment{}, errors.New("咪咕音乐未找到相关歌曲:" + keyword)
}
song := songs[0]
playURL, err := migu.GetDownloadURL(&song)
if err != nil {
return message.Segment{}, errors.Wrap(err, "获取咪咕播放链接失败")
}
if playURL == "" {
return message.Segment{}, errors.New("获取咪咕播放链接失败:链接为空")
}
return message.CustomMusic(
fmt.Sprintf("https://music.migu.cn/v3/music/song/%s", song.ID),
playURL,
song.Name,
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "migu"), nil
}
func getKuwoMusic(keyword string) (message.Segment, error) {
songs, err := kuwo.Search(keyword)
if err != nil {
return message.Segment{}, errors.Wrap(err, "酷我音乐搜索失败")
}
if len(songs) == 0 {
return message.Segment{}, errors.New("酷我音乐未找到相关歌曲:" + keyword)
}
song := songs[0]
playURL, err := kuwo.GetDownloadURL(&song)
if err != nil {
return message.Segment{}, errors.Wrap(err, "获取酷我播放链接失败")
}
if playURL == "" {
return message.Segment{}, errors.New("获取酷我播放链接失败:链接为空")
}
return message.CustomMusic(
fmt.Sprintf("https://www.kuwo.cn/play_detail/%s", song.ID),
playURL,
song.Name,
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "kuwo"), nil
}
func getKugouMusic(keyword string) (message.Segment, error) {
songs, err := kugou.Search(keyword)
if err != nil {
return message.Segment{}, errors.Wrap(err, "酷狗音乐搜索失败")
}
if len(songs) == 0 {
return message.Segment{}, errors.New("酷狗音乐未找到相关歌曲:" + keyword)
}
song := songs[0]
playURL, err := kugou.GetDownloadURL(&song)
if err != nil {
return message.Segment{}, errors.Wrap(err, "获取酷狗播放链接失败")
}
if playURL == "" {
return message.Segment{}, errors.New("获取酷狗播放链接失败:链接为空")
}
return message.CustomMusic(
"https://www.kugou.com/",
playURL,
song.Name,
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "kugou"), nil
}
func getNeteaseMusic(keyword string) (message.Segment, error) {
songs, err := netease.Search(keyword)
if err != nil {
return message.Segment{}, errors.Wrap(err, "网易云音乐搜索失败")
}
if len(songs) == 0 {
return message.Segment{}, errors.New("网易云音乐未找到相关歌曲:" + keyword)
}
song := songs[0]
playURL, err := netease.GetDownloadURL(&song)
if err != nil {
return message.Segment{}, errors.Wrap(err, "获取网易云播放链接失败")
}
if playURL == "" {
return message.Segment{}, errors.New("获取网易云播放链接失败:链接为空")
}
return message.CustomMusic(
fmt.Sprintf("https://music.163.com/#/song?id=%s", song.ID),
playURL,
song.Name,
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "163"), nil
}
func getQQMusic(keyword string) (message.Segment, error) {
songs, err := qq.Search(keyword)
if err != nil {
return message.Segment{}, errors.Wrap(err, "QQ音乐搜索失败")
}
if len(songs) == 0 {
return message.Segment{}, errors.New("QQ音乐未找到相关歌曲" + keyword)
}
song := songs[0]
playURL, err := qq.GetDownloadURL(&song)
if err != nil {
return message.Segment{}, errors.Wrap(err, "获取QQ音乐播放链接失败")
}
if playURL == "" {
return message.Segment{}, errors.New("获取QQ音乐播放链接失败链接为空")
}
return message.CustomMusic(
fmt.Sprintf("https://y.qq.com/n/ryqq/songDetail/%s", song.ID),
playURL,
song.Name,
).Add("content", song.Artist).Add("image", song.Cover).Add("subtype", "qq"), nil
}