diff --git a/coolq/bot.go b/coolq/bot.go
index 162a893..81eee07 100644
--- a/coolq/bot.go
+++ b/coolq/bot.go
@@ -201,61 +201,8 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int
bot.Client.SendGroupGift(uint64(groupId), uint64(i.Target), i.GiftId)
return 0
}
- if i, ok := elem.(*QQMusicElement); ok {
- var msgStyle uint32 = 4
- if i.MusicUrl == "" {
- msgStyle = 0 // fix vip song
- }
- ret, err := bot.Client.SendGroupRichMessage(groupId, 100497308, 1, msgStyle, client.RichClientInfo{
- Platform: 1,
- SdkVersion: "0.0.0",
- PackageName: "com.tencent.qqmusic",
- Signature: "cbd27cd7c861227d013a25b2d10f0799",
- }, &message.RichMessage{
- Title: i.Title,
- Summary: i.Summary,
- Url: i.Url,
- PictureUrl: i.PictureUrl,
- MusicUrl: i.MusicUrl,
- })
- if err != nil {
- log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupId, err)
- return -1
- }
- return bot.InsertGroupMessage(ret)
- }
- if i, ok := elem.(*CloudMusicElement); ok {
- ret, err := bot.Client.SendGroupRichMessage(groupId, 100495085, 1, 4, client.RichClientInfo{
- Platform: 1,
- SdkVersion: "0.0.0",
- PackageName: "com.netease.cloudmusic",
- Signature: "da6b069da1e2982db3e386233f68d76d",
- }, &message.RichMessage{
- Title: i.Title,
- Summary: i.Summary,
- Url: i.Url,
- PictureUrl: i.PictureUrl,
- MusicUrl: i.MusicUrl,
- })
- if err != nil {
- log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupId, err)
- return -1
- }
- return bot.InsertGroupMessage(ret)
- }
- if i, ok := elem.(*MiguMusicElement); ok {
- ret, err := bot.Client.SendGroupRichMessage(groupId, 1101053067, 1, 4, client.RichClientInfo{
- Platform: 1,
- SdkVersion: "0.0.0",
- PackageName: "cmccwm.mobilemusic",
- Signature: "6cdc72a439cef99a3418d2a78aa28c73",
- }, &message.RichMessage{
- Title: i.Title,
- Summary: i.Summary,
- Url: i.Url,
- PictureUrl: i.PictureUrl,
- MusicUrl: i.MusicUrl,
- })
+ if i, ok := elem.(*message.MusicShareElement); ok {
+ ret, err := bot.Client.SendGroupMusicShare(groupId, i)
if err != nil {
log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupId, err)
return -1
@@ -312,53 +259,8 @@ func (bot *CQBot) SendPrivateMessage(target int64, m *message.SendingMessage) in
newElem = append(newElem, gv)
continue
}
- if i, ok := elem.(*QQMusicElement); ok {
- var msgStyle uint32 = 4
- if i.MusicUrl == "" {
- msgStyle = 0 // fix vip song
- }
- bot.Client.SendFriendRichMessage(target, 100497308, 1, msgStyle, client.RichClientInfo{
- Platform: 1,
- SdkVersion: "0.0.0",
- PackageName: "com.tencent.qqmusic",
- Signature: "cbd27cd7c861227d013a25b2d10f0799",
- }, &message.RichMessage{
- Title: i.Title,
- Summary: i.Summary,
- Url: i.Url,
- PictureUrl: i.PictureUrl,
- MusicUrl: i.MusicUrl,
- })
- return 0
- }
- if i, ok := elem.(*CloudMusicElement); ok {
- bot.Client.SendFriendRichMessage(target, 100495085, 1, 4, client.RichClientInfo{
- Platform: 1,
- SdkVersion: "0.0.0",
- PackageName: "com.netease.cloudmusic",
- Signature: "da6b069da1e2982db3e386233f68d76d",
- }, &message.RichMessage{
- Title: i.Title,
- Summary: i.Summary,
- Url: i.Url,
- PictureUrl: i.PictureUrl,
- MusicUrl: i.MusicUrl,
- })
- return 0
- }
- if i, ok := elem.(*MiguMusicElement); ok {
- bot.Client.SendFriendRichMessage(target, 1101053067, 1, 4, client.RichClientInfo{
- Platform: 1,
- SdkVersion: "0.0.0",
- PackageName: "cmccwm.mobilemusic",
- Signature: "6cdc72a439cef99a3418d2a78aa28c73",
- }, &message.RichMessage{
- Title: i.Title,
- Summary: i.Summary,
- Url: i.Url,
- PictureUrl: i.PictureUrl,
- MusicUrl: i.MusicUrl,
- })
+ if i, ok := elem.(*message.MusicShareElement); ok {
+ bot.Client.SendFriendMusicShare(target, i)
return 0
}
newElem = append(newElem, elem)
diff --git a/coolq/cqcode.go b/coolq/cqcode.go
index 4032e1a..cdfe09e 100644
--- a/coolq/cqcode.go
+++ b/coolq/cqcode.go
@@ -49,26 +49,6 @@ type GiftElement struct {
GiftId message.GroupGift
}
-type MusicElement struct {
- Title string
- Summary string
- Url string
- PictureUrl string
- MusicUrl string
-}
-
-type QQMusicElement struct {
- MusicElement
-}
-
-type CloudMusicElement struct {
- MusicElement
-}
-
-type MiguMusicElement struct {
- MusicElement
-}
-
type LocalImageElement struct {
message.ImageElement
Stream io.ReadSeeker
@@ -90,10 +70,6 @@ func (e *GiftElement) Type() message.ElementType {
return message.At
}
-func (e *MusicElement) Type() message.ElementType {
- return message.Service
-}
-
var GiftId = [...]message.GroupGift{
message.SweetWink,
message.HappyCola,
@@ -699,7 +675,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf
return nil, errors.New("song not found")
}
aid := strconv.FormatInt(info.Get("track_info.album.id").Int(), 10)
- name := info.Get("track_info.name").Str + " - " + info.Get("track_info.singer.0.name").Str
+ name := info.Get("track_info.name").Str
mid := info.Get("track_info.mid").Str
albumMid := info.Get("track_info.album.mid").Str
pinfo, _ := global.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")
@@ -709,17 +685,18 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf
if len(aid) < 2 {
return nil, errors.New("song error")
}
- content := "来自go-cqhttp"
+ content := info.Get("track_info.singer.0.name").Str
if d["content"] != "" {
content = d["content"]
}
- return &QQMusicElement{MusicElement: MusicElement{
+ return &message.MusicShareElement{
+ MusicType: message.QQMusic,
Title: name,
Summary: content,
Url: jumpUrl,
PictureUrl: preview,
MusicUrl: purl,
- }}, nil
+ }, nil
}
if d["type"] == "163" {
info, err := global.NeteaseMusicSongInfo(d["id"])
@@ -737,41 +714,36 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf
if info.Get("artists.0").Exists() {
artistName = info.Get("artists.0.name").Str
}
- return &CloudMusicElement{MusicElement{
+ return &message.MusicShareElement{
+ MusicType: message.CloudMusic,
Title: name,
Summary: artistName,
Url: jumpUrl,
PictureUrl: picUrl,
MusicUrl: musicUrl,
- }}, nil
+ }, nil
}
if d["type"] == "custom" {
- if d["subtype"] == "qq" {
- return &QQMusicElement{MusicElement{
+ if d["subtype"] != "" {
+ var subtype = map[string]int{
+ "qq": message.QQMusic,
+ "163": message.CloudMusic,
+ "migu": message.MiguMusic,
+ "kugou": message.KugouMusic,
+ "kuwo": message.KuwoMusic,
+ }
+ var musicType = 0
+ if tp, ok := subtype[d["subtype"]]; ok {
+ musicType = tp
+ }
+ return &message.MusicShareElement{
+ MusicType: musicType,
Title: d["title"],
Summary: d["content"],
Url: d["url"],
PictureUrl: d["image"],
MusicUrl: d["purl"],
- }}, nil
- }
- if d["subtype"] == "163" {
- return &CloudMusicElement{MusicElement{
- Title: d["title"],
- Summary: d["content"],
- Url: d["url"],
- PictureUrl: d["image"],
- MusicUrl: d["purl"],
- }}, nil
- }
- if d["subtype"] == "migu" {
- return &MiguMusicElement{MusicElement{
- Title: d["title"],
- Summary: d["content"],
- Url: d["url"],
- PictureUrl: d["image"],
- MusicUrl: d["purl"],
- }}, nil
+ }, nil
}
xml := fmt.Sprintf(`- %s%s
`,
XmlEscape(d["title"]), d["url"], d["image"], d["audio"], XmlEscape(d["title"]), XmlEscape(d["content"]))
diff --git a/docs/cqhttp.md b/docs/cqhttp.md
index f660e64..f1da613 100644
--- a/docs/cqhttp.md
+++ b/docs/cqhttp.md
@@ -111,6 +111,54 @@ Type : `reply`
\
自定义回复示例: `[CQ:reply,text=Hello World,qq=10086,time=3376656000]`
+### 音乐分享
+
+```json
+{
+ "type": "music",
+ "data": {
+ "type": "163",
+ "id": "28949129"
+ }
+}
+```
+
+```
+[CQ:music,type=163,id=28949129]
+```
+
+| 参数名 | 收 | 发 | 可能的值 | 说明 |
+| --- | --- | --- | --- | --- |
+| `type` | | ✓ | `qq` `163` | 分别表示使用 QQ 音乐、网易云音乐 |
+| `id` | | ✓ | - | 歌曲 ID |
+
+### 音乐自定义分享
+
+```json
+{
+ "type": "music",
+ "data": {
+ "type": "custom",
+ "url": "http://baidu.com",
+ "audio": "http://baidu.com/1.mp3",
+ "title": "音乐标题"
+ }
+}
+```
+
+```
+[CQ:music,type=custom,url=http://baidu.com,audio=http://baidu.com/1.mp3,title=音乐标题]
+```
+
+| 参数名 | 收 | 发 | 可能的值 | 说明 |
+| --- | --- | --- | --- | --- |
+| `type` | | ✓ | `custom` | 表示音乐自定义分享 |
+| `subtype` | | ✓ | `qq,163,migu,kugou,kuwo` | 表示分享类型,不填写发送为xml卡片,推荐填写提高稳定性 |
+| `url` | | ✓ | - | 点击后跳转目标 URL |
+| `audio` | | ✓ | - | 音乐 URL |
+| `title` | | ✓ | - | 标题 |
+| `content` | | ✓ | - | 内容描述 |
+| `image` | | ✓ | - | 图片 URL |
### 红包
diff --git a/global/codec.go b/global/codec.go
index 188504f..1a6b35f 100644
--- a/global/codec.go
+++ b/global/codec.go
@@ -2,13 +2,13 @@ package global
import (
"crypto/md5"
- "errors"
"fmt"
"io/ioutil"
"os/exec"
"path"
"github.com/Mrs4s/go-cqhttp/global/codec"
+ "github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
@@ -32,7 +32,7 @@ func EncoderSilk(data []byte) ([]byte, error) {
h := md5.New()
_, err := h.Write(data)
if err != nil {
- return nil, err
+ return nil, errors.Wrap(err, "calc md5 failed")
}
tempName := fmt.Sprintf("%x", h.Sum(nil))
if silkPath := path.Join("data/cache", tempName+".silk"); PathExists(silkPath) {
@@ -40,7 +40,7 @@ func EncoderSilk(data []byte) ([]byte, error) {
}
slk, err := codec.EncodeToSilk(data, tempName, true)
if err != nil {
- return nil, err
+ return nil, errors.Wrap(err, "encode silk failed")
}
return slk, nil
}
@@ -51,7 +51,7 @@ func EncodeMP4(src string, dst string) error { // -y 覆盖文件
err := cmd1.Run()
if err != nil {
cmd2 := exec.Command("ffmpeg", "-i", src, "-y", "-c:v", "h264", "-c:a", "mp3", dst)
- return cmd2.Run()
+ return errors.Wrap(cmd2.Run(), "convert mp4 failed")
}
return err
}
@@ -59,5 +59,5 @@ func EncodeMP4(src string, dst string) error { // -y 覆盖文件
//ExtractCover 获取给定视频文件的Cover
func ExtractCover(src string, target string) error {
cmd := exec.Command("ffmpeg", "-i", src, "-y", "-r", "1", "-f", "image2", target)
- return cmd.Run()
+ return errors.Wrap(cmd.Run(), "extract video cover failed")
}
diff --git a/global/codec/codec.go b/global/codec/codec.go
index 6b053db..9b6115c 100644
--- a/global/codec/codec.go
+++ b/global/codec/codec.go
@@ -4,7 +4,7 @@
package codec
import (
- "errors"
+ "github.com/pkg/errors"
"io/ioutil"
"net/http"
"os"
@@ -63,7 +63,7 @@ func EncodeToSilk(record []byte, tempName string, useCache bool) ([]byte, error)
rawPath := path.Join(silkCachePath, tempName+".wav")
err := ioutil.WriteFile(rawPath, record, os.ModePerm)
if err != nil {
- return nil, err
+ return nil, errors.Wrap(err, "write temp file error")
}
defer os.Remove(rawPath)
@@ -71,7 +71,7 @@ func EncodeToSilk(record []byte, tempName string, useCache bool) ([]byte, error)
pcmPath := path.Join(silkCachePath, tempName+".pcm")
cmd := exec.Command("ffmpeg", "-i", rawPath, "-f", "s16le", "-ar", "24000", "-ac", "1", pcmPath)
if err = cmd.Run(); err != nil {
- return nil, err
+ return nil, errors.Wrap(err, "convert pcm file error")
}
defer os.Remove(pcmPath)
@@ -79,7 +79,7 @@ func EncodeToSilk(record []byte, tempName string, useCache bool) ([]byte, error)
silkPath := path.Join(silkCachePath, tempName+".silk")
cmd = exec.Command(getEncoderFilePath(), pcmPath, silkPath, "-rate", "24000", "-quiet", "-tencent")
if err = cmd.Run(); err != nil {
- return nil, err
+ return nil, errors.Wrap(err, "convert silk file error")
}
if !useCache {
defer os.Remove(silkPath)
diff --git a/go.mod b/go.mod
index 0ae114e..9f43444 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/Mrs4s/go-cqhttp
go 1.15
require (
- github.com/Mrs4s/MiraiGo v0.0.0-20210124065645-9549a32d954a
+ github.com/Mrs4s/MiraiGo v0.0.0-20210125093830-340977eb201f
github.com/dustin/go-humanize v1.0.0
github.com/gin-contrib/pprof v1.3.0
github.com/gin-gonic/gin v1.6.3
diff --git a/go.sum b/go.sum
index 0df7ac5..066b742 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,9 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/Mrs4s/MiraiGo v0.0.0-20210124065645-9549a32d954a h1:ov5QCDpZpsr+geKLVON7E63UqrpNF0oTiKuZwbKwEmo=
-github.com/Mrs4s/MiraiGo v0.0.0-20210124065645-9549a32d954a/go.mod h1:9V7DdSwpEfCKQNvLZhRnFJFkelTU0tPLfwR5l6UFF1Y=
+github.com/LXY1226/fastrand v0.0.0-20210121160840-7a3db3e79031 h1:DnoCySrXUFvtngW2kSkuBeZoPfvOgctJXjTulCn7eV0=
+github.com/LXY1226/fastrand v0.0.0-20210121160840-7a3db3e79031/go.mod h1:mEFi4jHUsE2sqQGSJ7eQfXnO8esMzEYcftiCGG+L/OE=
+github.com/Mrs4s/MiraiGo v0.0.0-20210125093830-340977eb201f h1:v86jOk27ypxD3gT48KJDy/Y5w7PIaTvabZYdDszr3w0=
+github.com/Mrs4s/MiraiGo v0.0.0-20210125093830-340977eb201f/go.mod h1:JBm2meosyXAASbl8mZ+mFZEkE/2cC7zNZdIOBe7+QhY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=