Skip to content
This repository was archived by the owner on Aug 16, 2024. It is now read-only.

Commit eb596d6

Browse files
authored
Merge pull request #43 from cyanray/dev/cyanray
支持语音消息发送
2 parents acf891b + 2a56768 commit eb596d6

File tree

7 files changed

+192
-6
lines changed

7 files changed

+192
-6
lines changed

examples/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,5 @@ api_exe(GroupMemberInfo)
3434
api_exe(GroupNameChange)
3535
api_exe(GroupConfig)
3636
api_exe(MemberCardChange)
37-
api_exe(Command)
37+
api_exe(Command)
38+
api_exe(VoiceMessage)

examples/VoiceMessage.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <iostream>
2+
// 使用静态库必须要在引入 mirai.h 前定义这个宏
3+
#define MIRAICPP_STATICLIB
4+
#include <mirai.h>
5+
6+
int main()
7+
{
8+
using namespace std;
9+
using namespace Cyan;
10+
system("chcp 65001");
11+
MiraiBot bot("127.0.0.1", 539);
12+
while (true)
13+
{
14+
try
15+
{
16+
bot.Auth("INITKEY7A3O1a9v", 1589588851_qq);
17+
break;
18+
}
19+
catch (const std::exception& ex)
20+
{
21+
cout << ex.what() << endl;
22+
}
23+
MiraiBot::SleepSeconds(1);
24+
}
25+
cout << "成功登录 bot。" << endl;
26+
27+
bot.On<GroupMessage>(
28+
[&](GroupMessage m)
29+
{
30+
try
31+
{
32+
MiraiVoice voice = bot.UploadGroupVoice("D:\\5.amr");
33+
m.Reply(MessageChain().Voice(voice));
34+
}
35+
catch (const std::exception& ex)
36+
{
37+
cout << ex.what() << endl;
38+
}
39+
});
40+
41+
42+
bot.EventLoop();
43+
44+
return 0;
45+
}

include/mirai/defs/message_chain.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "messages/JsonMessage.hpp"
2222
#include "messages/PokeMessage.hpp"
2323
#include "messages/QuoteMessage.hpp"
24+
#include "messages/VoiceMessage.hpp"
2425

2526
using std::vector;
2627

@@ -182,6 +183,11 @@ namespace Cyan
182183
return this->Add<PokeMessage>(poke);
183184
}
184185

186+
MessageChain& Voice(const VoiceMessage& voice)
187+
{
188+
return this->Add<VoiceMessage>(voice);
189+
}
190+
185191
string GetPlainText() const;
186192

187193
string GetPlainTextFirst() const;
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#pragma once
2+
#ifndef mirai_cpp_defs_messages_voice_message_hpp_H_
3+
#define mirai_cpp_defs_messages_image_message_hpp_H_
4+
5+
#include "mirai/defs/message_interface.hpp"
6+
#include "mirai/defs/qq_types.hpp"
7+
8+
namespace Cyan
9+
{
10+
class VoiceMessage : public IMessage
11+
{
12+
public:
13+
VoiceMessage() {}
14+
VoiceMessage(const MiraiVoice& m)
15+
{
16+
voiceId_ = m.Id;
17+
url_ = m.Url;
18+
path_ = m.Path;
19+
}
20+
virtual const string& GetType() const override
21+
{
22+
return type_;
23+
}
24+
virtual bool operator==(const IMessage& m) const override
25+
{
26+
if (auto m_ptr = dynamic_cast<const VoiceMessage*>(&m))
27+
{
28+
// 用 voiceId 作为判断依据,必须有一个 voiceId 不为空
29+
if (!m_ptr->voiceId_.empty() || !this->voiceId_.empty())
30+
{
31+
return (m_ptr->voiceId_ == this->voiceId_);
32+
}
33+
// 如果 voiceId 都为空,那么用 url 再判断一下
34+
if (!m_ptr->url_.empty() || !this->url_.empty())
35+
{
36+
return (m_ptr->url_ == this->url_);
37+
}
38+
// 如果 url 都为空,那么用 path 再判断一下
39+
if (!m_ptr->path_.empty() || !this->path_.empty())
40+
{
41+
return (m_ptr->path_ == this->path_);
42+
}
43+
// 三个参数都为空,两个空的 VoiceMessage 当然是相等的:
44+
return true;
45+
}
46+
// 类型都不同,直接不相等:
47+
return false;
48+
}
49+
virtual bool operator!=(const IMessage& m) const override
50+
{
51+
return !(*this == m);
52+
}
53+
virtual bool Set(const json& json) override
54+
{
55+
if (json["type"].is_null() || json["type"].get<string>() != this->GetType())
56+
throw std::runtime_error("给定的json不正确");
57+
if (!json["voiceId"].is_null())
58+
voiceId_ = json["voiceId"].get<string>();
59+
if (!json["url"].is_null())
60+
url_ = json["url"].get<string>();
61+
if (!json["path"].is_null())
62+
path_ = json["path"].get<string>();
63+
return true;
64+
}
65+
virtual json ToJson() const override
66+
{
67+
return
68+
{
69+
{ "type", type_ },
70+
{ "voiceId", voiceId_ },
71+
{ "url", url_ },
72+
{ "path", path_ }
73+
};
74+
}
75+
virtual ~VoiceMessage() {}
76+
77+
MiraiVoice ToMiraiVoice() const
78+
{
79+
MiraiVoice tmp;
80+
tmp.Id = voiceId_;
81+
tmp.Url = url_;
82+
tmp.Path = path_;
83+
return tmp;
84+
}
85+
86+
private:
87+
string type_ = "Voice";
88+
protected:
89+
string voiceId_;
90+
string url_;
91+
string path_;
92+
};
93+
94+
}
95+
#endif
96+

include/mirai/defs/qq_types.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ namespace Cyan
9292

9393
typedef MiraiImage TempImage;
9494

95+
struct MiraiVoice
96+
{
97+
string Id;
98+
string Url;
99+
string Path;
100+
};
101+
95102
// 预先声明 MiraiBot 类
96103
class EXPORTED MiraiBot;
97104

include/mirai/mirai_bot.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ namespace Cyan
7171
int GetRequiredApiVersionInt() const
7272
{
7373
// mirai-api-http v1.6.5
74-
return 10704;
74+
return 10800;
7575
}
7676

7777
/**
@@ -81,7 +81,7 @@ namespace Cyan
8181
string GetRequiredApiVersion() const
8282
{
8383
// mirai-api-http v1.6.5
84-
return "v1.7.4";
84+
return "v1.8.0";
8585
}
8686

8787
/**
@@ -154,6 +154,12 @@ namespace Cyan
154154
* \return 临时消息图片
155155
*/
156156
TempImage UploadTempImage(const string& fileName);
157+
/**
158+
* @brief 上传可以发给群组的语音
159+
* @param filename 文件名(amr文件)
160+
* @return MiraiVoice
161+
*/
162+
MiraiVoice UploadGroupVoice(const string& filename);
157163
/**
158164
* \brief 获得好友列表
159165
* \return vector<Friend_t>

src/mirai_bot.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,31 @@ namespace Cyan
255255
}
256256

257257

258+
MiraiVoice MiraiBot::UploadGroupVoice(const string& filename)
259+
{
260+
string voice_data = ReadFile(filename);
261+
httplib::MultipartFormDataItems items =
262+
{
263+
{ "sessionKey", sessionKey_, "", "" },
264+
{ "type", "group", "", "" },
265+
{ "voice", voice_data, std::to_string(rand()) + ".amr", "application/octet-stream" }
266+
};
267+
268+
auto res = http_client_.Post("/uploadVoice", items);
269+
270+
if (!res)
271+
throw runtime_error("网络错误");
272+
if (res->status != 200)
273+
throw std::runtime_error("[mirai-http-api error]: " + res->body);
274+
json re_json = json::parse(res->body);
275+
MiraiVoice result;
276+
result.Id = re_json["voiceId"].get<string>();
277+
if (!re_json["url"].is_null())
278+
result.Url = re_json["url"].get<string>();
279+
result.Path = re_json["path"].get<string>();
280+
return result;
281+
}
282+
258283
vector<Friend_t> MiraiBot::GetFriendList()
259284
{
260285
auto res = http_client_.Get(("/friendList?sessionKey=" + sessionKey_).data());
@@ -628,9 +653,9 @@ namespace Cyan
628653
}
629654

630655
MiraiBot& MiraiBot::RegisterCommand(
631-
const string& commandName,
632-
const vector<string> alias,
633-
const string& description,
656+
const string& commandName,
657+
const vector<string> alias,
658+
const string& description,
634659
const string& helpMessage)
635660
{
636661
json data =

0 commit comments

Comments
 (0)