cpp-mirai-client  v2.6.1
cpp client for mirai-api-http
MessageChain.hpp
浏览该文件的文档.
1// Copyright (C) 2022 Numendacil and contributors
2//
3// This program is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Affero General Public License as
5// published by the Free Software Foundation, either version 3 of the
6// License, or (at your option) any later version.
7//
8// This program is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU Affero General Public License for more details.
12//
13// You should have received a copy of the GNU Affero General Public License
14// along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16#ifndef MIRAI_MESSAGECHAIN_HPP_
17#define MIRAI_MESSAGECHAIN_HPP_
18
19#include <cassert>
20#include <cstddef>
21#include <ctime>
22#include <functional>
23#include <memory>
24#include <optional>
25#include <stdexcept>
26#include <type_traits>
27#include <utility>
28#include <vector>
29
32
33#include "AppMessage.hpp"
34#include "AtAllMessage.hpp"
35#include "AtMessage.hpp"
36#include "AudioMessage.hpp"
37#include "DiceMessage.hpp"
38#include "FaceMessage.hpp"
39#include "FileMessage.hpp"
40#include "ForwardMessage.hpp"
41#include "IMessage.hpp"
42#include "ImageMessage.hpp"
43#include "JsonMessage.hpp"
44#include "MiraiCodeMessage.hpp"
45#include "MusicShareMessage.hpp"
46#include "PlainMessage.hpp"
47#include "PokeMessage.hpp"
48#include "QuoteMessage.hpp"
49#include "SourceMessage.hpp"
50#include "XmlMessage.hpp"
51
52namespace Mirai
53{
54
55/**
56 * @brief 消息链对象,由一系列消息元素组成
57 *
58 * 可以使用类似STL容器的操作来访问各元素( `std::vector<std::unique_ptr<MessageElement>>` )
59 */
61{
62private:
63 // type traits
64 struct traits
65 {
66 template<typename T, typename TypeList> struct is_message_type_;
67
68 template<typename T, size_t... I>
69 struct is_message_type_<T, std::index_sequence<I...>> : public std::disjunction<std::is_same<T, GetType_t<MessageTypesList[I]>>...>
70 {
71 };
72
73 template<typename T>
74 using is_message_type = is_message_type_<T, std::make_index_sequence<MessageTypesList.size()>>;
75 };
76
77 template<typename MessageType> constexpr static void type_check_()
78 {
79 static_assert(std::is_base_of_v<IMessage, MessageType>,
80 "MessageType is not derived from IMessage"); // NOLINT(*-array-to-pointer-decay)
82 "Unsupported messsage type"); // NOLINT(*-array-to-pointer-decay)
83 };
84
85public:
86 /**
87 * @brief 消息元素对象
88 *
89 * 对不同消息类型的统一封装,储存着某一特定消息类型的对象
90 */
92 {
93 private:
94 std::unique_ptr<IMessage> msg_;
95 MessageTypes type_ = MessageTypes::ENUM_END; // For quick reference
96
97 template<
98 std::size_t... I, typename F,
99 typename Ret =
100 std::enable_if_t<(sizeof...(I) > 0), std::invoke_result_t<F, GetType_t<MessageTypesList[0]>&>> >
101 auto visit_(std::index_sequence<I...>, F&& f) -> std::enable_if_t<
102 std::conjunction_v<std::is_same<Ret, std::invoke_result_t<F, GetType_t<MessageTypesList[I]>&>>...>, Ret >
103 {
104 using FP = Ret (*)(F&&, MessageElement*);
105 static constexpr std::array<FP, sizeof...(I)> func = {
106 [](F&& f, MessageElement* p) { return f(static_cast<GetType_t<MessageTypesList[I]>&>(*p->msg_)); }...};
107
108 if (this->type_ == MessageTypes::ENUM_END)
109 throw std::runtime_error("Cannot call visit() on an empty MessageElement");
110 return func[static_cast<size_t>(this->type_)](std::forward<F>(f), this);
111 }
112
113 template< std::size_t... I, typename F,
114 typename Ret = std::enable_if_t<(sizeof...(I) > 0),
115 std::invoke_result_t<F, const GetType_t<MessageTypesList[0]>&>> >
116 auto cvisit_(std::index_sequence<I...>, F&& f) const -> std::enable_if_t<
117 std::conjunction_v<std::is_same<Ret, std::invoke_result_t<F, const GetType_t<MessageTypesList[I]>&>>...>,
118 Ret >
119 {
120 using FP = Ret (*)(F&&, const MessageElement*);
121 static constexpr std::array<FP, sizeof...(I)> func = {[](F&& f, const MessageElement* p) {
122 return f(static_cast<const GetType_t<MessageTypesList[I]>&>(*p->msg_));
123 }...};
124
125 if (this->type_ == MessageTypes::ENUM_END)
126 throw std::runtime_error("Cannot call visit() on an empty MessageElement");
127 return func[static_cast<size_t>(this->type_)](std::forward<F>(f), this);
128 }
129
130 // WARNING: Use this only if you know what you are doing
131 explicit MessageElement(std::unique_ptr<IMessage>&& msg, MessageTypes type) : msg_(std::move(msg)), type_(type)
132 {
133 // NOLINTNEXTLINE(*-array-to-pointer-decay)
134 assert(this->type_ == ((this->msg_) ? this->msg_->type() : MessageTypes::ENUM_END));
135 }
136
137 public:
138 /**
139 * @brief Constructors, conversion operators and destructor
140 *
141 */
142 ///@{
143
144 MessageElement() = default;
145
146 explicit MessageElement(std::unique_ptr<IMessage>&& msg) : msg_(std::move(msg))
147 {
148 if (msg_) this->type_ = this->msg_->type();
149 }
150
151 MessageElement& operator=(std::unique_ptr<IMessage>&& msg)
152 {
153 this->msg_ = std::move(msg);
154 if (msg_)
155 this->type_ = this->msg_->type();
156 return *this;
157 }
158
159 MessageElement(const MessageElement& rhs) : msg_(), type_(rhs.type_)
160 {
161 if (rhs.msg_) this->msg_ = rhs.msg_->clone();
162 }
163
165 {
166 if (&rhs != this)
167 {
168 this->type_ = rhs.type_;
169 if (rhs.msg_) this->msg_ = rhs.msg_->clone();
170 }
171 return *this;
172 }
173
174 MessageElement(MessageElement&&) noexcept = default;
175 MessageElement& operator=(MessageElement&&) noexcept = default;
176
177 ~MessageElement() = default;
178
179 explicit operator bool() const { return (bool)this->msg_; }
180
181 template<typename MessageType, typename... Args, typename Type = std::decay_t<MessageType>,
182 typename std::enable_if_t<traits::is_message_type<Type>::value, int> = 0>
183 explicit MessageElement(std::in_place_type_t<MessageType>, Args&&... args)
184 : msg_(std::make_unique<Type>(std::forward<Args>(args)...)), type_(Type::GetType())
185 {
186 }
187
188 template<typename MessageType, typename Type = std::decay_t<MessageType>,
189 typename std::enable_if_t<traits::is_message_type<Type>::value, int> = 0>
190 explicit MessageElement(MessageType&& m)
191 : msg_(std::make_unique<Type>(std::forward<MessageType>(m))), type_(Type::GetType())
192 {
193 }
194
195 template<typename MessageType, typename Type = std::decay_t<MessageType>,
196 typename std::enable_if_t<traits::is_message_type<Type>::value, int> = 0>
197 MessageElement& operator=(MessageType&& m)
198 {
199 if (this->msg_ && this->type_ == Type::GetType())
200 {
201 static_cast<Type&>(*this->msg_) = std::forward<MessageType>(m);
202 }
203 else
204 {
205 this->msg_ = std::make_unique<Type>(std::forward<MessageType>(m));
206 this->type_ = Type::GetType();
207 }
208 return *this;
209 }
210
211 // This function does not change the ownership of the input pointer
212 explicit MessageElement(IMessage* m) : msg_(m->clone()), type_(m->type()) {}
213
214 ///@}
215
216 /**
217 * @brief 获取所含消息的类型
218 *
219 * @return `MessageTypes`
220 */
221 MessageTypes type() const { return this->type_; }
222
223 /**
224 * @brief 检查消息是否可以用于发送
225 *
226 * 部分消息仅支持接收
227 * @return `bool`
228 */
229 bool allowSend() const
230 {
231 if (!this->msg_) throw std::runtime_error("MessageElement is empty");
232 return this->msg_->allowSend();
233 }
234
235 /**
236 * @brief 检查消息是否有效
237 *
238 * 发送无效消息( `valid() = false` )会导致mirai-api-http返回400或500错误,并抛出异常。
239 * 检测的内容靠测试经验和mirai-api-http源码确定, `valid() = true` 不保证一定能发送成功。
240 * @return `bool`
241 */
242 bool valid() const
243 {
244 if (!this->msg_) throw std::runtime_error("MessageElement is empty");
245 return this->msg_->valid();
246 }
247
248 /**
249 * @brief 转换为某一特定类型的消息,类型错误时将抛出异常
250 *
251 * @tparam MessageType 消息类型
252 * @return MessageType& 对象的引用
253 */
254 ///@{
255 template<typename MessageType> MessageType& as()
256 {
257 type_check_<MessageType>();
258
259 if (!this->msg_) throw std::runtime_error("MessageElement is empty");
260 if (this->type_ != MessageType::GetType())
261 throw TypeDismatchError(to_string(this->type_), to_string(MessageType::GetType()));
262 return static_cast<MessageType&>(*this->msg_);
263 }
264
265 template<typename MessageType> const MessageType& as() const
266 {
267 type_check_<std::decay_t<MessageType>>();
268
269 if (!this->msg_) throw std::runtime_error("MessageElement is empty");
270 if (this->type_ != MessageType::GetType())
271 throw TypeDismatchError(to_string(this->type_), to_string(MessageType::GetType()));
272 return static_cast<const MessageType&>(*this->msg_);
273 }
274 ///@}
275
276 /**
277 * @brief 对此消息元素应用visitor,类似 `std::visit`
278 *
279 * @tparam Callable
280 * @param f 可调用对象
281 * @return auto 所有输入的返回类型必须一致
282 */
283 ///@{
284 template<typename Callable> auto visit(Callable&& f)
285 {
286 return this->visit_(std::make_index_sequence<MessageTypesList.size()>{}, std::forward<Callable>(f));
287 }
288
289 template<typename Callable> auto visit(Callable&& f) const
290 {
291 return this->cvisit_(std::make_index_sequence<MessageTypesList.size()>{}, std::forward<Callable>(f));
292 }
293 ///@}
294
295 struct Serializable;
296 };
297
298
299 /**
300 * @brief 消息来源信息
301 *
302 * 一般只存在于直接接收到的消息链中,转发消息与引用消息中的消息链不会含有该信息
303 */
305 {
306 /// 消息id
308 /// 消息时间戳
309 std::time_t time = 0;
310 };
311
312protected:
313 using MessageContainer = std::vector<MessageElement>;
315
316public:
317 MessageChain() = default;
318
321 MessageChain(MessageChain&& rhs) noexcept;
322 MessageChain& operator=(MessageChain&& rhs) noexcept;
323 ~MessageChain() = default;
324
325 /**
326 * @brief STL-like interface
327 *
328 */
329 ///@{
330
331 // I hate this
332
333 using value_type = MessageContainer::value_type;
334 using allocator_type = MessageContainer::allocator_type;
335 using size_type = MessageContainer::size_type;
336 using difference_type = MessageContainer::difference_type;
337 using reference = MessageContainer::reference;
338 using const_reference = MessageContainer::const_reference;
339 using pointer = MessageContainer::pointer;
340 using const_pointer = MessageContainer::const_pointer;
341 using reverse_iterator = MessageContainer::reverse_iterator;
342 using const_reverse_iterator = MessageContainer::const_reverse_iterator;
343 using iterator = MessageContainer::iterator;
344 using const_iterator = MessageContainer::const_iterator;
345
346 bool empty() const noexcept { return this->message_.empty(); }
347 size_type size() const noexcept { return this->message_.size(); }
348 void reserve(size_type new_cap) { return this->message_.reserve(new_cap); }
349 void shrink_to_fit() noexcept { return this->message_.shrink_to_fit(); }
350 size_type max_size() const noexcept { return this->message_.max_size(); }
351 size_type capacity() const noexcept { return this->message_.capacity(); }
352
353 void clear() noexcept { return this->message_.clear(); }
354 iterator erase(const_iterator pos) { return this->message_.erase(pos); }
355 iterator erase(const_iterator first, const_iterator last) { return this->message_.erase(first, last); }
356 void pop_back() { return this->message_.pop_back(); }
357 void resize(size_type count) { return this->message_.resize(count); }
358
359 iterator begin() noexcept { return this->message_.begin(); }
360 const_iterator begin() const noexcept { return this->message_.begin(); }
361 const_iterator cbegin() const noexcept { return this->message_.cbegin(); }
362 iterator end() noexcept { return this->message_.end(); }
363 const_iterator end() const noexcept { return this->message_.end(); }
364 const_iterator cend() const noexcept { return this->message_.cend(); }
365 reverse_iterator rbegin() noexcept { return this->message_.rbegin(); }
366 const_reverse_iterator crbegin() const noexcept { return this->message_.crbegin(); }
367 reverse_iterator rend() noexcept { return this->message_.rend(); }
368 const_reverse_iterator crend() const noexcept { return this->message_.crend(); }
369
370 const_reference operator[](size_type n) const noexcept { return this->message_[n]; }
371 reference operator[](size_type n) noexcept { return this->message_[n]; }
372 const_reference at(size_type n) const { return this->message_.at(n); }
373 reference at(size_type n) { return this->message_.at(n); }
374 const_reference back() const { return this->message_.back(); }
375 reference back() { return this->message_.back(); }
376 const_reference front() const { return this->message_.front(); }
377 reference front() { return this->message_.front(); }
378
379 ///@}
380
381 // Element Insertion
382
383 /**
384 * @brief 在消息链结尾添加消息元素
385 *
386 * 类似 `std::vector::push_back()`
387 * @tparam MessageType 消息类型
388 * @param m 要添加的消息
389 * @return reference to *this
390 */
391
392 template<typename MessageType> MessageChain& push_back(MessageType&& m)
393 {
394 type_check_<std::decay_t<MessageType>>();
395
396 this->message_.push_back(MessageElement(std::forward<MessageType>(m)));
397 return *this;
398 }
399
400 /**
401 * @brief 在消息链结尾直接构造消息元素
402 *
403 * 类似 `std::vector::emplace_back()`。
404 * @tparam MessageType 消息类型
405 * @tparam Args 参数类型
406 * @param args 构造消息元素的参数
407 * @return reference to *this
408 */
409 template<typename MessageType, typename... Args> MessageChain& emplace_back(Args&&... args)
410 {
411 type_check_<MessageType>();
412
413 this->message_.emplace_back(std::in_place_type_t<MessageType>{}, std::forward<Args>(args)...);
414 return *this;
415 }
416
417 /**
418 * @brief 在消息链结尾直接构造消息元素
419 *
420 * 类似 `std::vector::emplace_back()`。
421 * @tparam Type `MessageTypes`
422 * @tparam Args 参数类型
423 * @param args 构造消息元素的参数
424 * @return reference to *this
425 */
426 template<MessageTypes Type, typename... Args> MessageChain& emplace_back(Args&&... args)
427 {
428 return this->emplace_back<GetType_t<Type>>(std::forward<Args>(args)...);
429 }
430
431 /**
432 * @brief 在消息链中插入元素
433 *
434 * 类似 `std::vector::insert()`。
435 * @tparam MessageType 消息类型
436 * @param pos 插入位置
437 * @param m 要添加的消息
438 * @return 插入后新元素所在的位置
439 */
440 template<typename MessageType> iterator insert(const_iterator pos, MessageType&& m)
441 {
442 type_check_<std::decay_t<MessageType>>();
443
444 return this->message_.insert(pos, MessageElement(std::forward<MessageType>(m)));
445 }
446
447 /**
448 * @brief 在消息链中插入元素
449 *
450 * 类似 `std::vector::emplace()`。
451 * @tparam MessageType 消息类型
452 * @tparam Args 参数类型
453 * @param pos 插入位置
454 * @param args 构造对应消息的参数
455 * @return 插入后新元素所在的位置
456 */
457 template<typename MessageType, typename... Args> iterator emplace(const_iterator pos, Args&&... args)
458 {
459 type_check_<MessageType>();
460 return this->message_.emplace(pos, std::in_place_type_t<MessageType>{}, std::forward<Args>(args)...);
461 }
462
463 /**
464 * @brief 在消息链中插入元素
465 *
466 * @tparam Type `MessageTypes`
467 * @tparam Args 参数类型
468 * @param pos 插入位置
469 * @param args 构造对应消息的参数
470 * @return 插入后新元素所在的位置
471 */
472 template<MessageTypes Type, typename... Args> iterator emplace(const_iterator pos, Args&&... args)
473 {
474 return this->emplace<GetType_t<Type>>(pos, std::forward<Args>(args)...);
475 }
476
477 /// 拼接两个消息链
478 ///@{
481 ///@}
482
483 /// 添加消息元素到消息链结尾
484 ///@{
487
488 template<typename MessageType>
489 auto operator+=(MessageType&& m)
490 -> std::enable_if_t<traits::is_message_type<std::decay_t<MessageType>>::value, MessageChain&>
491 {
492 return *this += MessageElement(std::forward<MessageType>(m));
493 }
494 ///@}
495
496 /// 拼接两个消息链
497 friend MessageChain operator+(const MessageChain& lhs, const MessageChain& rhs);
498
499 /// 添加消息元素到消息链结尾
500 ///@{
501 friend MessageChain operator+(const MessageChain& lhs, const MessageElement& m);
502 friend MessageChain operator+(const MessageElement& m, const MessageChain& rhs) { return rhs + m; }
503
504 template<typename MessageType>
505 friend auto operator+(const MessageChain& lhs, MessageType&& m)
506 -> std::enable_if_t<traits::is_message_type<std::decay_t<MessageType>>::value, MessageChain>
507 {
508 return lhs + MessageElement(std::forward<MessageType>(m));
509 }
510
511 template<typename MessageType>
512 friend auto operator+(MessageType&& m, const MessageChain& rhs)
513 -> std::enable_if_t<traits::is_message_type<std::decay_t<MessageType>>::value, MessageChain>
514 {
515 return rhs + MessageElement(std::forward<MessageType>(m));
516 }
517 ///@}
518
519 // Element Access
520
521 /**
522 * @brief 获取指定下标处的消息
523 *
524 * 若消息类型与实际类型不匹配会抛出 `TypeDismatchError` 异常
525 * @tparam MessageType 消息类型
526 * @param i 下标
527 * @return 该消息元素的引用
528 */
529 ///@{
530
531 template<typename MessageType> MessageType& GetAt(size_type i) { return this->message_.at(i).as<MessageType>(); }
532
533 template<typename MessageType> const MessageType& GetAt(size_type i) const
534 {
535 return this->message_.at(i).as<MessageType>();
536 }
537
538 ///@}
539
540 /**
541 * @brief 获取指定下标处的消息
542 *
543 * 若消息类型与实际类型不匹配会抛出 `TypeDismatchError` 异常
544 * @tparam Type `MessageTypes`
545 * @param i 下标
546 * @return 该消息元素的引用
547 */
548 ///@{
549
550 template<MessageTypes Type> GetType_t<Type>& GetAt(size_type i) { return this->GetAt<GetType_t<Type>>(i); }
551
552 template<MessageTypes Type> const GetType_t<Type>& GetAt(size_type i) const
553 {
554 return this->GetAt<GetType_t<Type>>(i);
555 }
556
557 ///@}
558
559 /**
560 * @brief 获取指定下标处的消息类型
561 *
562 * @param i 下标
563 * @return Type `MessageTypes`
564 */
565 MessageTypes GetType(size_type i) const { return this->message_.at(i).type(); }
566
567 /**
568 * @brief 获取所有指定类型的消息元素
569 *
570 * 该方法将拷贝消息元素
571 * @tparam MessageType 消息类型
572 * @return `std::vector<MessageType>`
573 */
574 template<typename MessageType> std::vector<MessageType> GetAll() const
575 {
576 type_check_<MessageType>();
577
578 std::vector<MessageType> v;
579 for (const auto& p : this->message_)
580 {
581 if (p.type() == MessageType::GetType()) v.push_back(p.as<MessageType>());
582 }
583 return v;
584 }
585
586 /**
587 * @brief 获取所有指定类型的消息元素
588 *
589 * 该方法将拷贝消息元素
590 * @tparam Type 消息类型
591 * @return `std::vector<GetType_t<Type>>`
592 */
593 template<MessageTypes Type> auto GetAll() const { return this->GetAll<GetType_t<Type>>(); }
594
595 /**
596 * @brief 获取所有指定类型的消息元素的引用
597 *
598 * @tparam MessageType 消息类型
599 * @return `std::vector<std::reference_wrapper<MessageType>>`
600 */
601 ///@{
602
603 template<typename MessageType> std::vector<std::reference_wrapper<MessageType>> GetAllRef()
604 {
605 type_check_<MessageType>();
606
607 std::vector<std::reference_wrapper<MessageType>> v;
608 for (auto& p : this->message_)
609 {
610 if (p.type() == MessageType::GetType()) v.push_back(std::ref(p.as<MessageType>()));
611 }
612 return v;
613 }
614
615 template<typename MessageType> std::vector<std::reference_wrapper<const MessageType>> GetAllRef() const
616 {
617 type_check_<MessageType>();
618
619 std::vector<std::reference_wrapper<const MessageType>> v;
620 for (const auto& p : this->message_)
621 {
622 if (p.type() == MessageType::GetType()) v.push_back(std::cref(p.as<MessageType>()));
623 }
624 return v;
625 }
626
627 ///@}
628
629 /**
630 * @brief 获取所有指定类型的消息元素的引用
631 *
632 * @tparam Type 消息类型
633 * @return `std::vector<std::reference_wrapper<GetType_t<Type>>>`
634 */
635 ///@{
636
637 template<MessageTypes Type> auto GetAllRef() { return this->GetAllRef<GetType_t<Type>>(); }
638
639 template<MessageTypes Type> auto GetAllRef() const { return this->GetAllRef<GetType_t<Type>>(); }
640
641 ///@}
642
643
644 /**
645 * @brief 获取消息链中的来源信息
646 *
647 * @return 来源信息,若无则返回 `std::nullopt`
648 */
649 std::optional<SourceInfo> GetSourceInfo() const;
650
651 // Serialization
652
653 /**
654 * @brief 去除消息链中的无效消息
655 *
656 * 无效消息指 `IMessage::valid() = false` 的消息
657 */
658 void RemoveInvalid();
659
660 /**
661 * @brief 检查消息链是否有效
662 *
663 * 要求所有消息元素均有效,且消息不为空(存在至少一条可以发送的消息元素)
664 * @return `bool`
665 */
666 bool valid() const;
667
668 // Helper functions
669
670 /// 在消息链结尾构造 `AppMessage`,返回自身的引用
671 template<typename... Args> MessageChain& App(Args&&... args)
672 {
673 return this->emplace_back<AppMessage>(std::forward<Args>(args)...);
674 }
675
676 /// 在消息链结尾构造 `AtAllMessage`,返回自身的引用
677 template<typename... Args> MessageChain& AtAll(Args&&... args)
678 {
679 return this->emplace_back<AtAllMessage>(std::forward<Args>(args)...);
680 }
681
682 /// 在消息链结尾构造 `AtMessage`,返回自身的引用
683 template<typename... Args> MessageChain& At(Args&&... args)
684 {
685 return this->emplace_back<AtMessage>(std::forward<Args>(args)...);
686 }
687
688 /// 在消息链结尾构造 `AudioMessage`,返回自身的引用
689 template<typename... Args> MessageChain& Audio(Args&&... args)
690 {
691 return this->emplace_back<AudioMessage>(std::forward<Args>(args)...);
692 }
693
694 /// 在消息链结尾构造 `DiceMessage`,返回自身的引用
695 template<typename... Args> MessageChain& Dice(Args&&... args)
696 {
697 return this->emplace_back<DiceMessage>(std::forward<Args>(args)...);
698 }
699
700 /// 在消息链结尾构造 `FaceMessage`,返回自身的引用
701 template<typename... Args> MessageChain& Face(Args&&... args)
702 {
703 return this->emplace_back<FaceMessage>(std::forward<Args>(args)...);
704 }
705
706 /// 在消息链结尾构造 `FlashImageMessage`,返回自身的引用
707 template<typename... Args> MessageChain& Flash(Args&&... args)
708 {
709 return this->emplace_back<FlashImageMessage>(std::forward<Args>(args)...);
710 }
711
712 /// 在消息链结尾构造 `ImageMessage`,返回自身的引用
713 template<typename... Args> MessageChain& Image(Args&&... args)
714 {
715 return this->emplace_back<ImageMessage>(std::forward<Args>(args)...);
716 }
717
718 /// 在消息链结尾构造 `JsonMessage`,返回自身的引用
719 template<typename... Args> MessageChain& Json(Args&&... args)
720 {
721 return this->emplace_back<JsonMessage>(std::forward<Args>(args)...);
722 }
723
724 /// 在消息链结尾构造 `MiraiCodeMessage`,返回自身的引用
725 template<typename... Args> MessageChain& MiraiCode(Args&&... args)
726 {
727 return this->emplace_back<MiraiCodeMessage>(std::forward<Args>(args)...);
728 }
729
730 /// 在消息链结尾构造 `PlainMessage`,返回自身的引用
731 template<typename... Args> MessageChain& Plain(Args&&... args)
732 {
733 return this->emplace_back<PlainMessage>(std::forward<Args>(args)...);
734 }
735
736 /// 在消息链结尾构造 `PokeMessage`,返回自身的引用
737 template<typename... Args> MessageChain& Poke(Args&&... args)
738 {
739 return this->emplace_back<PokeMessage>(std::forward<Args>(args)...);
740 }
741
742 /// 在消息链结尾构造 `XmlMessage`,返回自身的引用
743 template<typename... Args> MessageChain& Xml(Args&&... args)
744 {
745 return this->emplace_back<XmlMessage>(std::forward<Args>(args)...);
746 }
747
748 /// 在消息链结尾插入 `ForwardMessage`,返回自身的引用
749 template<typename... Args> MessageChain& Forward(Args&&... args)
750 {
751 return this->emplace_back<ForwardMessage>(std::forward<Args>(args)...);
752 }
753
754 struct Serializable;
755};
756
758
759} // namespace Mirai
760
761#endif
Common interface for all message types
Definition: IMessage.hpp:34
MessageElement()=default
Constructors, conversion operators and destructor
MessageElement & operator=(const MessageElement &rhs)
Constructors, conversion operators and destructor
MessageElement(std::in_place_type_t< MessageType >, Args &&... args)
Constructors, conversion operators and destructor
MessageElement & operator=(std::unique_ptr< IMessage > &&msg)
Constructors, conversion operators and destructor
bool allowSend() const
检查消息是否可以用于发送
auto visit(Callable &&f)
对此消息元素应用visitor,类似 std::visit
MessageElement(const MessageElement &rhs)
Constructors, conversion operators and destructor
MessageElement(MessageType &&m)
Constructors, conversion operators and destructor
MessageElement & operator=(MessageType &&m)
Constructors, conversion operators and destructor
MessageTypes type() const
获取所含消息的类型
MessageType & as()
转换为某一特定类型的消息,类型错误时将抛出异常
bool valid() const
检查消息是否有效
const MessageType & as() const
转换为某一特定类型的消息,类型错误时将抛出异常
MessageElement(MessageElement &&) noexcept=default
Constructors, conversion operators and destructor
MessageElement(IMessage *m)
Constructors, conversion operators and destructor
auto visit(Callable &&f) const
对此消息元素应用visitor,类似 std::visit
MessageElement(std::unique_ptr< IMessage > &&msg)
Constructors, conversion operators and destructor
消息链对象,由一系列消息元素组成
MessageContainer::difference_type difference_type
STL-like interface
iterator erase(const_iterator first, const_iterator last)
STL-like interface
std::vector< MessageType > GetAll() const
获取所有指定类型的消息元素
reverse_iterator rbegin() noexcept
STL-like interface
MessageChain & operator+=(const MessageChain &rhs)
MessageChain & Audio(Args &&... args)
在消息链结尾构造 AudioMessage,返回自身的引用
MessageTypes GetType(size_type i) const
获取指定下标处的消息类型
reverse_iterator rend() noexcept
STL-like interface
bool empty() const noexcept
STL-like interface
const MessageType & GetAt(size_type i) const
获取指定下标处的消息
const_reference front() const
STL-like interface
auto GetAllRef()
获取所有指定类型的消息元素的引用
void shrink_to_fit() noexcept
STL-like interface
friend auto operator+(MessageType &&m, const MessageChain &rhs) -> std::enable_if_t< traits::is_message_type< std::decay_t< MessageType > >::value, MessageChain >
GetType_t< Type > & GetAt(size_type i)
获取指定下标处的消息
MessageContainer::const_reverse_iterator const_reverse_iterator
STL-like interface
void resize(size_type count)
STL-like interface
MessageContainer::const_iterator const_iterator
STL-like interface
MessageContainer::pointer pointer
STL-like interface
MessageChain()=default
const_iterator cbegin() const noexcept
STL-like interface
const_reference back() const
STL-like interface
size_type size() const noexcept
STL-like interface
MessageContainer::allocator_type allocator_type
STL-like interface
MessageChain & At(Args &&... args)
在消息链结尾构造 AtMessage,返回自身的引用
std::vector< MessageElement > MessageContainer
const_iterator begin() const noexcept
STL-like interface
MessageChain & Xml(Args &&... args)
在消息链结尾构造 XmlMessage,返回自身的引用
~MessageChain()=default
iterator insert(const_iterator pos, MessageType &&m)
在消息链中插入元素
MessageChain & Json(Args &&... args)
在消息链结尾构造 JsonMessage,返回自身的引用
const_iterator cend() const noexcept
STL-like interface
MessageContainer::const_reference const_reference
STL-like interface
MessageChain & Poke(Args &&... args)
在消息链结尾构造 PokeMessage,返回自身的引用
iterator begin() noexcept
STL-like interface
MessageChain & Flash(Args &&... args)
在消息链结尾构造 FlashImageMessage,返回自身的引用
const_reverse_iterator crend() const noexcept
STL-like interface
reference at(size_type n)
STL-like interface
std::vector< std::reference_wrapper< const MessageType > > GetAllRef() const
获取所有指定类型的消息元素的引用
MessageContainer message_
auto GetAll() const
获取所有指定类型的消息元素
size_type max_size() const noexcept
STL-like interface
iterator erase(const_iterator pos)
STL-like interface
void clear() noexcept
STL-like interface
MessageContainer::reverse_iterator reverse_iterator
STL-like interface
MessageContainer::size_type size_type
STL-like interface
std::optional< SourceInfo > GetSourceInfo() const
获取消息链中的来源信息
MessageType & GetAt(size_type i)
获取指定下标处的消息
size_type capacity() const noexcept
STL-like interface
MessageChain & Forward(Args &&... args)
在消息链结尾插入 ForwardMessage,返回自身的引用
const_reference operator[](size_type n) const noexcept
STL-like interface
bool valid() const
检查消息链是否有效
iterator end() noexcept
STL-like interface
void pop_back()
STL-like interface
MessageChain & AtAll(Args &&... args)
在消息链结尾构造 AtAllMessage,返回自身的引用
std::vector< std::reference_wrapper< MessageType > > GetAllRef()
获取所有指定类型的消息元素的引用
reference front()
STL-like interface
MessageChain & App(Args &&... args)
在消息链结尾构造 AppMessage,返回自身的引用
MessageChain & Dice(Args &&... args)
在消息链结尾构造 DiceMessage,返回自身的引用
MessageChain & Plain(Args &&... args)
在消息链结尾构造 PlainMessage,返回自身的引用
MessageContainer::iterator iterator
STL-like interface
const_iterator end() const noexcept
STL-like interface
MessageChain(const MessageChain &rhs)
const_reverse_iterator crbegin() const noexcept
STL-like interface
void reserve(size_type new_cap)
STL-like interface
reference back()
STL-like interface
const_reference at(size_type n) const
STL-like interface
MessageChain & operator=(const MessageChain &rhs)
iterator emplace(const_iterator pos, Args &&... args)
在消息链中插入元素
reference operator[](size_type n) noexcept
STL-like interface
MessageContainer::value_type value_type
STL-like interface
friend auto operator+(const MessageChain &lhs, MessageType &&m) -> std::enable_if_t< traits::is_message_type< std::decay_t< MessageType > >::value, MessageChain >
void RemoveInvalid()
去除消息链中的无效消息
MessageChain & MiraiCode(Args &&... args)
在消息链结尾构造 MiraiCodeMessage,返回自身的引用
friend MessageChain operator+(const MessageChain &lhs, const MessageChain &rhs)
拼接两个消息链
MessageContainer::const_pointer const_pointer
STL-like interface
MessageChain & Face(Args &&... args)
在消息链结尾构造 FaceMessage,返回自身的引用
const GetType_t< Type > & GetAt(size_type i) const
获取指定下标处的消息
auto GetAllRef() const
获取所有指定类型的消息元素的引用
auto operator+=(MessageType &&m) -> std::enable_if_t< traits::is_message_type< std::decay_t< MessageType > >::value, MessageChain & >
MessageChain & emplace_back(Args &&... args)
在消息链结尾直接构造消息元素
MessageChain & push_back(MessageType &&m)
在消息链结尾添加消息元素
MessageContainer::reference reference
STL-like interface
friend MessageChain operator+(const MessageElement &m, const MessageChain &rhs)
MessageChain & Image(Args &&... args)
在消息链结尾构造 ImageMessage,返回自身的引用
类型匹配错误
Definition: Exceptions.hpp:117
所有mirai相关的对象的命名空间
std::string to_string(EventTypes type)
MessageChain::MessageElement MessageElement
int64_t MessageId_t
消息id类型,用于撤回消息和引用消息
Definition: BasicTypes.hpp:35
typename GetType< type >::type GetType_t
constexpr std::array< MessageTypes, static_cast< size_t >(MessageTypes::ENUM_END)> MessageTypesList
STL namespace
用于类型之间转换的辅助模板
std::time_t time
消息时间戳