Skip to content

Commit 4da30e8

Browse files
committed
music
1 parent c873c6f commit 4da30e8

File tree

6 files changed

+131
-4
lines changed

6 files changed

+131
-4
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ require (
2121
github.com/sirupsen/logrus v1.8.1
2222
github.com/smartystreets/goconvey v1.6.4 // indirect
2323
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
24+
github.com/tidwall/gjson v1.11.0
2425
github.com/zserge/lorca v0.1.10
2526
golang.org/x/mobile v0.0.0-20211207041440-4e6c2922fdee
2627
golang.org/x/net v0.0.0-20211123203042-d83791d6bcd9 // indirect
@@ -38,7 +39,6 @@ require (
3839
github.com/leodido/go-urn v1.2.1 // indirect
3940
github.com/modern-go/reflect2 v1.0.1 // indirect
4041
github.com/pierrec/lz4/v4 v4.1.11 // indirect
41-
github.com/tidwall/gjson v1.11.0 // indirect
4242
github.com/tidwall/match v1.1.1 // indirect
4343
github.com/tidwall/pretty v1.2.0 // indirect
4444
github.com/ugorji/go/codec v1.2.6 // indirect

go.sum

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
2-
github.com/Mrs4s/MiraiGo v0.0.0-20211219072930-afb81a32aa75 h1:4xgd1/lhAKHv/2sAbxbR38hDwt/HfOiWlVOqSJc544E=
3-
github.com/Mrs4s/MiraiGo v0.0.0-20211219072930-afb81a32aa75/go.mod h1:HI05ardsa5HE1Z2xTw69dytmaqqRWv4ajD5Jpnycqqw=
42
github.com/Mrs4s/MiraiGo v0.0.0-20211221051559-21f8feb419c9 h1:py7g4UrnKWnn7LRYU1RAvKDSo9VVslanNJI5MV+4QXo=
53
github.com/Mrs4s/MiraiGo v0.0.0-20211221051559-21f8feb419c9/go.mod h1:HI05ardsa5HE1Z2xTw69dytmaqqRWv4ajD5Jpnycqqw=
64
github.com/RomiChan/protobuf v0.0.0-20211204042931-ff4f35848737 h1:p4o7/eSoP39jwnGZz08N1IpH/mNzg9SdCn7kPM9A9BE=

pkg/bot/api_handler.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@ func preProcessGroupSendingMessage(cli *client.QQClient, groupCode int64, m *mes
141141
newElements = append(newElements, gm)
142142
continue
143143
}
144+
if i, ok := element.(*message.MusicShareElement); ok {
145+
// TODO 撤回?
146+
_, err := cli.SendGroupMusicShare(groupCode, i)
147+
if err != nil {
148+
log.Errorf("failed to send music, %+v", err)
149+
continue
150+
}
151+
continue
152+
}
144153
newElements = append(newElements, element)
145154
}
146155
m.Elements = newElements

pkg/bot/proto2mirai.go

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package bot
22

33
import (
44
"bytes"
5+
"fmt"
6+
57
"io/ioutil"
68
"math/rand"
79
"os"
@@ -17,7 +19,9 @@ import (
1719

1820
"github.com/Mrs4s/MiraiGo/client"
1921
"github.com/Mrs4s/MiraiGo/message"
22+
"github.com/Mrs4s/MiraiGo/utils"
2023
log "github.com/sirupsen/logrus"
24+
"github.com/tidwall/gjson"
2125
)
2226

2327
func EmptyText() *message.TextElement {
@@ -74,6 +78,8 @@ func ProtoMsgToMiraiMsg(cli *client.QQClient, msgList []*onebot.Message, notConv
7478
messageChain = append(messageChain, ProtoTtsToMiraiTts(cli, protoMsg.Data))
7579
case "video":
7680
messageChain = append(messageChain, ProtoVideoToMiraiVideo(cli, protoMsg.Data))
81+
case "music":
82+
messageChain = append(messageChain, ProtoMusicToMiraiMusic(cli, protoMsg.Data))
7783
default:
7884
log.Errorf("不支持的消息类型 %+v", protoMsg)
7985
}
@@ -373,7 +379,7 @@ func ProtoTtsToMiraiTts(cli *client.QQClient, data map[string]string) (m message
373379
return &message.VoiceElement{Data: b}
374380
}
375381

376-
func ProtoVideoToMiraiVideo(cli *client.QQClient, data map[string]string) (m message.IMessageElement) {
382+
func ProtoVideoToMiraiVideo(_ *client.QQClient, data map[string]string) (m message.IMessageElement) {
377383
elem := &clz.MyVideoElement{}
378384
coverUrl, ok := data["cover"]
379385
if !ok {
@@ -439,3 +445,96 @@ func ProtoVideoToMiraiVideo(cli *client.QQClient, data map[string]string) (m mes
439445
elem.CoverUrl = coverUrl // 仅用于发送日志展示
440446
return elem
441447
}
448+
449+
func ProtoMusicToMiraiMusic(_ *client.QQClient, data map[string]string) (m message.IMessageElement) {
450+
if data["type"] == "qq" {
451+
info, err := util.QQMusicSongInfo(data["id"])
452+
if err != nil {
453+
log.Warnf("failed to get qq music song info, %+v", data["id"])
454+
return EmptyText()
455+
}
456+
if !info.Get("track_info").Exists() {
457+
log.Warnf("music track_info not found, %+v", info.String())
458+
return EmptyText()
459+
}
460+
name := info.Get("track_info.name").Str
461+
mid := info.Get("track_info.mid").Str
462+
albumMid := info.Get("track_info.album.mid").Str
463+
pinfo, _ := util.GetBytes("http://u.y.qq.com/cgi-bin/musicu.fcg?g_tk=2034008533&uin=0&format=json&data={\"comm\":{\"ct\":23,\"cv\":0},\"url_mid\":{\"module\":\"vkey.GetVkeyServer\",\"method\":\"CgiGetVkey\",\"param\":{\"guid\":\"4311206557\",\"songmid\":[\"" + mid + "\"],\"songtype\":[0],\"uin\":\"0\",\"loginflag\":1,\"platform\":\"23\"}}}&_=1599039471576")
464+
jumpURL := "https://i.y.qq.com/v8/playsong.html?platform=11&appshare=android_qq&appversion=10030010&hosteuin=oKnlNenz7i-s7c**&songmid=" + mid + "&type=0&appsongtype=1&_wv=1&source=qq&ADTAG=qfshare"
465+
purl := gjson.ParseBytes(pinfo).Get("url_mid.data.midurlinfo.0.purl").Str
466+
preview := "http://y.gtimg.cn/music/photo_new/T002R180x180M000" + albumMid + ".jpg"
467+
content := info.Get("track_info.singer.0.name").Str
468+
if data["content"] != "" {
469+
content = data["content"]
470+
}
471+
return &message.MusicShareElement{
472+
MusicType: message.QQMusic,
473+
Title: name,
474+
Summary: content,
475+
Url: jumpURL,
476+
PictureUrl: preview,
477+
MusicUrl: purl,
478+
}
479+
}
480+
if data["type"] == "163" {
481+
info, err := util.NeteaseMusicSongInfo(data["id"])
482+
if err != nil {
483+
log.Warnf("failed to get qq music song info, %+v", data["id"])
484+
return EmptyText()
485+
}
486+
if !info.Exists() {
487+
log.Warnf("netease song not fount")
488+
return EmptyText()
489+
}
490+
name := info.Get("name").Str
491+
jumpURL := "https://y.music.163.com/m/song/" + data["id"]
492+
musicURL := "http://music.163.com/song/media/outer/url?id=" + data["id"]
493+
picURL := info.Get("album.picUrl").Str
494+
artistName := ""
495+
if info.Get("artists.0").Exists() {
496+
artistName = info.Get("artists.0.name").Str
497+
}
498+
return &message.MusicShareElement{
499+
MusicType: message.CloudMusic,
500+
Title: name,
501+
Summary: artistName,
502+
Url: jumpURL,
503+
PictureUrl: picURL,
504+
MusicUrl: musicURL,
505+
}
506+
}
507+
if data["type"] == "custom" {
508+
if data["subtype"] != "" {
509+
var subType int
510+
switch data["subtype"] {
511+
default:
512+
subType = message.QQMusic
513+
case "163":
514+
subType = message.CloudMusic
515+
case "migu":
516+
subType = message.MiguMusic
517+
case "kugou":
518+
subType = message.KugouMusic
519+
case "kuwo":
520+
subType = message.KuwoMusic
521+
}
522+
return &message.MusicShareElement{
523+
MusicType: subType,
524+
Title: data["title"],
525+
Summary: data["content"],
526+
Url: data["url"],
527+
PictureUrl: data["image"],
528+
MusicUrl: data["audio"],
529+
}
530+
}
531+
xml := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="2" templateID="1" action="web" brief="[分享] %s" sourceMsgId="0" url="%s" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2"><audio cover="%s" src="%s"/><title>%s</title><summary>%s</summary></item><source name="音乐" icon="https://i.gtimg.cn/open/app_icon/01/07/98/56/1101079856_100_m.png" url="http://web.p.qq.com/qqmpmobile/aio/app.html?id=1101079856" action="app" a_actionData="com.tencent.qqmusic" i_actionData="tencent1101079856://" appid="1101079856" /></msg>`,
532+
utils.XmlEscape(data["title"]), data["url"], data["image"], data["audio"], utils.XmlEscape(data["title"]), utils.XmlEscape(data["content"]))
533+
return &message.ServiceElement{
534+
Id: 60,
535+
Content: xml,
536+
SubType: "music",
537+
}
538+
}
539+
return EmptyText()
540+
}

pkg/bot/raw2mirai.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ func RawMsgToMiraiMsg(cli *client.QQClient, str string) []message.IMessageElemen
8282
elemList = append(elemList, ProtoTtsToMiraiTts(cli, attrMap))
8383
case "video":
8484
elemList = append(elemList, ProtoVideoToMiraiVideo(cli, attrMap))
85+
case "music":
86+
elemList = append(elemList, ProtoMusicToMiraiMusic(cli, attrMap))
8587
default:
8688
log.Warnf("不支持的类型 %s", code)
8789
elemList = append(elemList, message.NewText(code))

pkg/util/util.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
"github.com/pkg/errors"
2626
log "github.com/sirupsen/logrus"
27+
"github.com/tidwall/gjson"
2728
)
2829

2930
var (
@@ -357,3 +358,21 @@ func DownloadFileMultiThreading(url, path string, limit int64, threadCount int,
357358
wg.Wait()
358359
return lastErr
359360
}
361+
362+
// QQMusicSongInfo 通过给定id在QQ音乐上查找曲目信息
363+
func QQMusicSongInfo(id string) (gjson.Result, error) {
364+
d, err := GetBytes(`https://u.y.qq.com/cgi-bin/musicu.fcg?format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data={%22comm%22:{%22ct%22:24,%22cv%22:0},%22songinfo%22:{%22method%22:%22get_song_detail_yqq%22,%22param%22:{%22song_type%22:0,%22song_mid%22:%22%22,%22song_id%22:` + id + `},%22module%22:%22music.pf_song_detail_svr%22}}`)
365+
if err != nil {
366+
return gjson.Result{}, err
367+
}
368+
return gjson.ParseBytes(d).Get("songinfo.data"), nil
369+
}
370+
371+
// NeteaseMusicSongInfo 通过给定id在wdd音乐上查找曲目信息
372+
func NeteaseMusicSongInfo(id string) (gjson.Result, error) {
373+
d, err := GetBytes(fmt.Sprintf("http://music.163.com/api/song/detail/?id=%s&ids=%%5B%s%%5D", id, id))
374+
if err != nil {
375+
return gjson.Result{}, err
376+
}
377+
return gjson.ParseBytes(d).Get("songs.0"), nil
378+
}

0 commit comments

Comments
 (0)