18#include <condition_variable>
30#include <nlohmann/json.hpp>
33#include <libmirai/Serialization/Events/Events.hpp>
34#include <libmirai/Serialization/Types/Types.hpp>
35#include <libmirai/Utils/Common.hpp>
37#include <libmirai/Utils/ThreadPool.hpp>
116 if (!this->
adaptor_)
throw std::runtime_error(
"Null pointer: No adaptor is set");
120 LOG_DEBUG(*(this->
logger_),
"Connecting to Mirai-Api-Http, initializing threadpool");
122 this->
pool_ = std::make_unique<Utils::ThreadPool>(this->
PoolSize_);
126 this->
adaptor_->OnConnectionEstablished(
131 "MessageClient connected with response header: " + [&]() -> std::string
134 for (
const auto& p : event.
headers)
135 header +=
"\n" + p.first +
": " + p.second;
139 std::unique_lock<std::shared_mutex> lk(this->
mtx_);
151 "MessageClient connection closed: " + [&]() -> std::string
155 msg +=
"\nReason: " +
event.reason;
156 msg +=
"\nClosedByRemote: ";
157 msg +=
event.remote ?
"True" :
"False";
161 std::unique_lock<std::shared_mutex> lk(this->
mtx_);
172 "MessageClient failed to connect with error: " + [&event]() -> std::string
176 msg +=
"\nReason: " +
event.reason;
177 msg +=
"\nDecompressionError: ";
178 msg +=
event.DecompressionError ?
"True" :
"False";
185 [
this](
const std::string& message)
191 json msg = json::parse(message);
192 if (!msg.contains(
"data"))
return;
195 json data = msg.at(
"data");
196 if (!data.is_object())
return;
197 data = Utils::ParseResponse(data);
198 if (!(data.contains(
"type") && data.at(
"type").is_string()))
return;
200 auto type = data.at(
"type").get<
EventTypes>();
208 [&data,
this](
auto&& handler)
210 using FuncType = std::decay_t<
decltype(handler)>;
221 if constexpr (!std::disjunction_v< std::is_same<EventType, ClientConnectionEstablishedEvent>,
222 std::is_same<EventType, ClientConnectionErrorEvent>,
223 std::is_same<EventType, ClientConnectionClosedEvent>,
224 std::is_same<EventType, ClientParseErrorEvent> >)
227 event.SetClient_(
this);
228 from_json(std::move(data), event);
229 (void)this->
pool_->enqueue(handler, std::move(event));
238 catch (
const std::exception& e)
263 this->
pool_->stop(WaitForFinish);
264 this->
pool_ =
nullptr;
292 if (!std::holds_alternative<FriendMessageEvent>(msg))
296 return std::get<FriendMessageEvent>(msg);
303 if (!std::holds_alternative<GroupMessageEvent>(msg))
307 return std::get<GroupMessageEvent>(msg);
314 if (!std::holds_alternative<TempMessageEvent>(msg))
318 return std::get<TempMessageEvent>(msg);
325 if (!std::holds_alternative<StrangerMessageEvent>(msg))
329 return std::get<StrangerMessageEvent>(msg);
375 std::optional<MessageId_t> QuoteId)
const
381 std::optional<MessageId_t> QuoteId)
const
387 std::optional<MessageId_t> QuoteId)
const
393 std::optional<MessageId_t> QuoteId)
const
399 std::optional<MessageId_t> QuoteId)
const
405 std::optional<MessageId_t> QuoteId)
const
407 return this->
adaptor_->SendTempMessage(this->
GetSessionKey_(), MemberId, GroupId, std::move(message), QuoteId);
445 std::time_t TimeEnd)
const
452 int64_t size,
bool withDownloadInfo)
const
491 string content)
const
493 return this->
adaptor_->FileUpload(this->
GetSessionKey_(), std::move(UploadPath), GroupId,
"group", std::move(name), std::move(content));
497 std::istream& file)
const
501 while (file.read(buffer,
sizeof(buffer)))
502 s.append(buffer,
sizeof(buffer));
503 s.append(buffer, file.gcount());
504 return this->
UploadGroupFile(GroupId, std::move(UploadPath), std::move(name), std::move(s));
509 std::function<
bool(
size_t offset, std::ostream& sink,
bool& finish)> ContentProvider)
const
511 return this->
adaptor_->FileUploadChunked(this->
GetSessionKey_(), std::move(UploadPath), GroupId,
"group", std::move(name),
512 std::move(ContentProvider));
525 while (file.read(buffer,
sizeof(buffer)))
526 s.append(buffer,
sizeof(buffer));
527 s.append(buffer, file.gcount());
532 std::function<
bool(
size_t offset, std::ostream& sink,
bool& finish)> ContentProvider)
const
547 while (file.read(buffer,
sizeof(buffer)))
548 s.append(buffer,
sizeof(buffer));
549 s.append(buffer, file.gcount());
554 std::function<
bool(
size_t offset, std::ostream& sink,
bool& finish)> ContentProvider)
const
569 while (file.read(buffer,
sizeof(buffer)))
570 s.append(buffer,
sizeof(buffer));
571 s.append(buffer, file.gcount());
591 while (file.read(buffer,
sizeof(buffer)))
592 s.append(buffer,
sizeof(buffer));
593 s.append(buffer, file.gcount());
598 std::function<
bool(
size_t offset, std::ostream& sink,
bool& finish)> ContentProvider)
const
667 return this->
adaptor_->SetGroupConfig(this->
GetSessionKey_(), GroupId, std::move(name), std::nullopt, AllowMemberInvite);
677 return this->
adaptor_->SetMemberInfo(this->
GetSessionKey_(), GroupId, member, std::move(name), std::move(title));
692 bool ToNewMember,
bool pinned,
bool ShowEditCard,
bool ShowPopup,
693 bool RequireConfirm)
const
696 ToNewMember, pinned, ShowEditCard, ShowPopup, RequireConfirm);
711 string message)
const
713 return this->
adaptor_->RespNewFriendRequestEvent(this->
GetSessionKey_(), EventId, FromId, GroupId, (
int)operation,
718 string message)
const
721 event.
GetGroupId(), (
int)operation, std::move(message));
725 string message)
const
727 return this->
adaptor_->RespMemberJoinRequestEvent(this->
GetSessionKey_(), EventId, FromId, GroupId, (
int)operation,
732 string message)
const
735 event.
GetGroupId(), (
int)operation, std::move(message));
740 string message)
const
742 return this->
adaptor_->RespBotInvitedJoinGroupRequestEvent(this->
GetSessionKey_(), EventId, FromId, GroupId,
743 (
int)operation, std::move(message));
748 string message)
const
750 return this->
adaptor_->RespBotInvitedJoinGroupRequestEvent(
756 string description)
const
758 return this->
adaptor_->CmdRegister(this->
GetSessionKey_(), std::move(name), std::move(alias), std::move(usage), std::move(description));
773 return this->
adaptor_->CallAPI(path, method, data);
#define LOG_TRACE(logger, msg)
#define LOG_DEBUG(logger, msg)
QQ_t GetUserId() const
获取邀请人QQ
GID_t GetGroupId() const
获取群聊id
int64_t GetEventId() const
获取事件id,唯一标识符
std::string GetId() const
获取文件id
std::string GetPath() const
获取文件名路径
static constexpr EventTypes GetType()
获取事件类型
QQ_t GetUserId() const
获取申请人QQ
GID_t GetGroupId() const
获取群聊id
int64_t GetEventId() const
获取事件id,唯一标识符
EventCallback< ClientConnectionClosedEvent > ConnectionClosedCallback_
std::vector< MessageChain > GetRoamingFriendMessage(QQ_t qq, std::time_t TimeStart=0, std::time_t TimeEnd=std::numeric_limits< std::time_t >::max()) const
获取好友漫游消息
void Connect()
连接mirai-api-http
traits::EventCallbackVariant EventHandler
GroupAudio UploadGroupAudio(string content) const
上传群聊语音
void NudgeFriend(QQ_t qq) const
发送好友戳一戳消息
string GetMiraiApiHttpVersion() const
获取mirai-api-http插件的版本号
MessageId_t SendFriendMessage(QQ_t qq, const MessageChain &message, std::optional< MessageId_t > QuoteId=std::nullopt) const
发送好友消息
void RemoveGroupFile(GID_t GroupId, const FilePath &dir) const
删除群文件
std::vector< GroupAnnouncement > GetAnnouncementList(GID_t GroupId, int64_t offset=0, int64_t size=0) const
获取群公告列表
GroupFileInfo UploadGroupFile(GID_t GroupId, string UploadPath, string name, string content) const
上传群文件
std::unordered_map< EventTypes, EventHandler > EventHandlers_
GroupConfig GetGroupConfig(GID_t GroupId) const
获取群设置
StrangerMessageEvent GetStrangerMessage(MessageId_t id, QQ_t qq) const
从消息id获取陌生人消息
string CallAPI(const string &path, const string &method, const string &data) const
直接向mirai-api-http发送请求
void RecallGroupMessage(MessageId_t id, GID_t GroupId) const
撤回群聊消息
UserProfile GetFriendProfile(QQ_t qq) const
获取好友用户资料
GroupImage UploadGroupImage(string content) const
上传群聊图片
UserProfile GetUserProfile(QQ_t qq) const
获取用户资料
void SetGroupConfig(GID_t GroupId, string name="", std::optional< bool > AllowMemberInvite=std::nullopt) const
修改群设置
std::unique_ptr< IAdaptor > adaptor_
std::vector< GroupMember > GetMemberList(GID_t GroupId) const
获取群成员列表
UserProfile GetMemberProfile(GID_t GroupId, QQ_t MemberId) const
获取群成员用户资料
void RespMemberJoinRequestEvent(int64_t EventId, QQ_t FromId, GID_t GroupId, MemberJoinRequestOp operation, string message) const
处理用户申请入群事件 MemberJoinRequestEvent
void SendNudge(const NudgeTarget &target) const
发送头像戳一戳消息
void Mute(GID_t GroupId, QQ_t member, std::chrono::seconds time) const
禁言群成员
void RespNewFriendRequestEvent(int64_t EventId, QQ_t FromId, GID_t GroupId, NewFriendRequestOp operation, string message) const
处理添加好友申请事件 NewFriendRequestEvent
void DeleteAnnouncement(GID_t GroupId, string fid) const
删除群公告
GroupMember GetMemberInfo(GID_t GroupId, QQ_t member) const
获取群成员资料
std::vector< QQ_t > GetBotList() const
获取mirai中可用的QQBot列表
void ExecuteCommand(const MessageChain &command) const
执行指令
void SetMemberInfo(GID_t GroupId, QQ_t member, string name="", string title="") const
设置群成员资料
std::vector< GroupMember > GetLatestMemberList(GID_t GroupId) const
获取最新群成员列表
GroupFileInfo GetGroupFileInfo(GID_t GroupId, const FilePath &dir, bool withDownloadInfo=false) const
获取群文件信息
void MuteAll(GID_t GroupId) const
禁言全体成员
MessageId_t SendTempMessage(QQ_t MemberId, GID_t GroupId, const MessageChain &message, std::optional< MessageId_t > QuoteId=std::nullopt) const
发送临时会话消息
void NudgeGroup(QQ_t MemberId, GID_t GroupId) const
发送群聊戳一戳消息
EventCallback< ClientConnectionEstablishedEvent > ConnectionEstablishedCallback_
EventCallback< ClientParseErrorEvent > ParseErrorCallback_
std::shared_ptr< ILogger > logger_
TempImage UploadTempImage(string content) const
上传临时会话图片
void Disconnect(bool WaitForFinish=false)
断开与mirai-api-http的连接
std::vector< GroupFileInfo > GetGroupFileList(GID_t GroupId, const FilePath &dir={}, int64_t offset=0, int64_t size=0, bool withDownloadInfo=false) const
获取群文件列表
void DeleteFriend(QQ_t qq) const
删除好友
void RegisterCommand(string name, std::vector< string > alias, string usage, string description) const
注册指令
std::string GetSessionKey_() const
EventCallback< ClientConnectionErrorEvent > ConnectionErrorCallback_
MessageId_t SendGroupMessage(GID_t GroupId, const MessageChain &message, std::optional< MessageId_t > QuoteId=std::nullopt) const
发送群聊消息
TempMessageEvent GetTempMessage(MessageId_t id, GID_t GroupId) const
从消息id获取临时消息
std::vector< User > GetFriendList() const
获取好友列表
FriendMessageEvent GetFriendMessage(MessageId_t id, QQ_t qq) const
从消息id获取好友消息
GroupMessageEvent GetGroupMessage(MessageId_t id, GID_t GroupId) const
从消息id获取群聊消息
void MoveGroupFile(GID_t GroupId, const FilePath &FileDir, const FilePath &MoveToDir) const
移动群文件
void LeaveGroup(GID_t GroupId) const
退出群聊
std::unique_ptr< Utils::ThreadPool > pool_
void Kick(GID_t GroupId, QQ_t member, string message, bool block=false) const
移除群成员
void SetEssence(GID_t GroupId, MessageId_t MessageId) const
设置群精华消息
void NudgeStranger(QQ_t qq) const
发送陌生人戳一戳消息
std::vector< Group > GetGroupList() const
获取群聊列表
QQ_t GetBotQQ() const
获取Bot账号
void RenameGroupFile(GID_t GroupId, const FilePath &FileDir, string NewName) const
重命名群文件
void RecallFriendMessage(MessageId_t id, QQ_t qq) const
撤回好友消息
void UnmuteAll(GID_t GroupId) const
解除全体禁言
FriendImage UploadFriendImage(string content) const
上传好友图片
GroupFileInfo CreateGroupFileDirectory(GID_t GroupId, string directory) const
创建群文件夹
GroupAnnouncement PublishAnnouncement(GID_t GroupId, string content, MiraiImage cover={}, bool ToNewMember=false, bool pinned=false, bool ShowEditCard=false, bool ShowPopup=false, bool RequireConfirm=false) const
发布群公告
UserProfile GetBotProfile() const
获取Bot用户资料
void SetGroupAdmin(GID_t GroupId, QQ_t member, bool assign=true) const
设置群管理员
void RespBotInvitedJoinGroupRequestEvent(int64_t EventId, QQ_t FromId, GID_t GroupId, BotInvitedJoinGroupRequestOp operation, string message) const
处理Bot被邀请入群事件 BotInvitedJoinGroupRequestEvent
void Unmute(GID_t GroupId, QQ_t member) const
解除群成员禁言
GID_t GetGroupId() const
获取申请人来自的群聊,若无则返回 0_gid
QQ_t GetUserId() const
获取申请人QQ
int64_t GetEventId() const
获取事件id,唯一标识符
QQ_t GetTarget() const
返回戳一戳的对象
GID_t GetGroup() const
返回戳一戳所在的群聊
NudgeType GetNudgeType() const
返回戳一戳类型
NewFriendRequestOp
处理好友申请的操作
std::string to_string(EventTypes type)
BotInvitedJoinGroupRequestOp
处理被邀请入群的操作
int64_t MessageId_t
消息id类型,用于撤回消息和引用消息
MemberJoinRequestOp
处理用户入群申请的操作
std::map< std::string, std::string > headers
接收的文件头信息
std::string fid
公告id,唯一标识符
std::string base64
图片base64编码