feat(plugins): Added message read/update methods to the Channel API. (#6650)
This PR adds methods to read and update messages in a channel. Specifically, it adds: - message_snapshot - last_message - replace_message/replace_message_at - clear_messages - find_message_by_id - has_messages - count_messages Reviewed-by: Mm2PL <mm2pl+gh@kotmisia.pl>
This commit is contained in:
@@ -75,6 +75,11 @@ bool Channel::hasMessages() const
|
||||
return !this->messages_.empty();
|
||||
}
|
||||
|
||||
size_t Channel::countMessages() const
|
||||
{
|
||||
return this->messages_.size();
|
||||
}
|
||||
|
||||
std::vector<MessagePtr> Channel::getMessageSnapshot() const
|
||||
{
|
||||
return this->messages_.getSnapshot();
|
||||
@@ -85,6 +90,13 @@ std::vector<MessagePtr> Channel::getMessageSnapshot(size_t nItems) const
|
||||
return this->messages_.lastN(nItems);
|
||||
}
|
||||
|
||||
std::vector<MessagePtrMut> Channel::getMessageSnapshotMut(size_t nItems) const
|
||||
{
|
||||
return this->messages_.lastNBy<MessagePtrMut>(nItems, [](const auto &msg) {
|
||||
return std::const_pointer_cast<Message>(msg);
|
||||
});
|
||||
}
|
||||
|
||||
MessagePtr Channel::getLastMessage() const
|
||||
{
|
||||
auto last = this->messages_.last();
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace chatterino {
|
||||
|
||||
struct Message;
|
||||
using MessagePtr = std::shared_ptr<const Message>;
|
||||
using MessagePtrMut = std::shared_ptr<Message>;
|
||||
|
||||
class Channel : public std::enable_shared_from_this<Channel>, public MessageSink
|
||||
{
|
||||
@@ -87,6 +88,12 @@ public:
|
||||
std::vector<MessagePtr> getMessageSnapshot() const;
|
||||
std::vector<MessagePtr> getMessageSnapshot(size_t nItems) const;
|
||||
|
||||
/// Essentially the same as #getMessageSnapshot(size_t), but the returned
|
||||
/// vector holds `std::shared_ptr<Message>`. This should only be used in
|
||||
/// plugins, because they take messages as `Message` but check that they're
|
||||
/// frozen.
|
||||
std::vector<MessagePtrMut> getMessageSnapshotMut(size_t nItems) const;
|
||||
|
||||
/// Returns the last message (the one at the bottom). If the channel has no
|
||||
/// messages, this will return an empty shared pointer.
|
||||
MessagePtr getLastMessage() const;
|
||||
@@ -122,6 +129,8 @@ public:
|
||||
|
||||
bool hasMessages() const;
|
||||
|
||||
size_t countMessages() const;
|
||||
|
||||
void applySimilarityFilters(const MessagePtr &message) const final;
|
||||
|
||||
MessageSinkTraits sinkTraits() const final;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
# include "common/Channel.hpp"
|
||||
# include "controllers/commands/CommandController.hpp"
|
||||
# include "controllers/plugins/SolTypes.hpp"
|
||||
# include "messages/Message.hpp"
|
||||
# include "providers/twitch/TwitchChannel.hpp"
|
||||
# include "providers/twitch/TwitchIrcServer.hpp"
|
||||
# include "util/WeakPtrHelpers.hpp"
|
||||
@@ -119,6 +120,79 @@ void ChannelRef::add_message(std::shared_ptr<Message> &message,
|
||||
this->strong()->addMessage(message, ctx, overrideFlags);
|
||||
}
|
||||
|
||||
std::vector<MessagePtrMut> ChannelRef::message_snapshot(size_t n_items)
|
||||
{
|
||||
return this->strong()->getMessageSnapshotMut(n_items);
|
||||
}
|
||||
|
||||
MessagePtrMut ChannelRef::last_message()
|
||||
{
|
||||
return std::const_pointer_cast<Message>(this->strong()->getLastMessage());
|
||||
}
|
||||
|
||||
void ChannelRef::replace_message(const MessagePtrMut &message,
|
||||
const MessagePtrMut &replacement)
|
||||
{
|
||||
if (!message || !replacement)
|
||||
{
|
||||
throw std::runtime_error("Invalid message");
|
||||
}
|
||||
|
||||
this->strong()->replaceMessage(message, replacement);
|
||||
}
|
||||
|
||||
void ChannelRef::replace_message_hint(const MessagePtrMut &message,
|
||||
const MessagePtrMut &replacement,
|
||||
size_t hint)
|
||||
{
|
||||
if (!message || !replacement)
|
||||
{
|
||||
throw std::runtime_error("Invalid message");
|
||||
}
|
||||
if (hint == 0)
|
||||
{
|
||||
throw std::runtime_error("Invalid index");
|
||||
}
|
||||
|
||||
this->strong()->replaceMessage(hint - 1, message, replacement);
|
||||
}
|
||||
|
||||
void ChannelRef::replace_message_at(size_t index,
|
||||
const MessagePtrMut &replacement)
|
||||
{
|
||||
if (!replacement)
|
||||
{
|
||||
throw std::runtime_error("Invalid message");
|
||||
}
|
||||
if (index == 0)
|
||||
{
|
||||
throw std::runtime_error("Invalid index");
|
||||
}
|
||||
|
||||
this->strong()->replaceMessage(index - 1, replacement);
|
||||
}
|
||||
|
||||
void ChannelRef::clear_messages()
|
||||
{
|
||||
this->strong()->clearMessages();
|
||||
}
|
||||
|
||||
MessagePtrMut ChannelRef::find_message_by_id(const QString &id)
|
||||
{
|
||||
return std::const_pointer_cast<Message>(
|
||||
this->strong()->findMessageByID(id));
|
||||
}
|
||||
|
||||
bool ChannelRef::has_messages()
|
||||
{
|
||||
return this->strong()->hasMessages();
|
||||
}
|
||||
|
||||
size_t ChannelRef::count_messages()
|
||||
{
|
||||
return this->strong()->countMessages();
|
||||
}
|
||||
|
||||
bool ChannelRef::is_twitch_channel()
|
||||
{
|
||||
return this->strong()->isTwitchChannel();
|
||||
@@ -202,10 +276,21 @@ void ChannelRef::createUserType(sol::table &c2)
|
||||
"get_name",&ChannelRef::get_name,
|
||||
"get_type", &ChannelRef::get_type,
|
||||
"get_display_name", &ChannelRef::get_display_name,
|
||||
"is_twitch_channel", &ChannelRef::is_twitch_channel,
|
||||
|
||||
// Messages
|
||||
"send_message", &ChannelRef::send_message,
|
||||
"add_system_message", &ChannelRef::add_system_message,
|
||||
"add_message", &ChannelRef::add_message,
|
||||
"is_twitch_channel", &ChannelRef::is_twitch_channel,
|
||||
"message_snapshot", &ChannelRef::message_snapshot,
|
||||
"last_message", &ChannelRef::last_message,
|
||||
"replace_message", sol::overload(&ChannelRef::replace_message,
|
||||
&ChannelRef::replace_message_hint),
|
||||
"replace_message_at", &ChannelRef::replace_message_at,
|
||||
"clear_messages", &ChannelRef::clear_messages,
|
||||
"find_message_by_id", &ChannelRef::find_message_by_id,
|
||||
"has_messages", &ChannelRef::has_messages,
|
||||
"count_messages", &ChannelRef::count_messages,
|
||||
|
||||
// TwitchChannel
|
||||
"get_room_modes", &ChannelRef::get_room_modes,
|
||||
|
||||
@@ -85,6 +85,86 @@ public:
|
||||
*/
|
||||
void add_message(std::shared_ptr<Message> &message, sol::variadic_args va);
|
||||
|
||||
// FIXME: create a separate type for Sol container wrappers
|
||||
/**
|
||||
* Get a list of messages in this channel (starting from the most recent messages).
|
||||
* The snapshot is returned as a usertype that wraps a C++ object.
|
||||
*
|
||||
* @lua@param n_items number Number of messages to retrieve. This is an upper bound, the actual number of messages returned might be lower.
|
||||
* @lua@return c2.Message[]
|
||||
* @exposed c2.Channel:message_snapshot
|
||||
*/
|
||||
std::vector<MessagePtrMut> message_snapshot(size_t n_items);
|
||||
|
||||
/**
|
||||
* Get the most recent message. If this channel doesn't have any message, this returns `nil`.
|
||||
*
|
||||
* @lua@return c2.Message?
|
||||
* @exposed c2.Channel:last_message
|
||||
*/
|
||||
MessagePtrMut last_message();
|
||||
|
||||
/**
|
||||
* Replace a specific message with a different one.
|
||||
*
|
||||
* @lua@param message c2.Message The message to replace.
|
||||
* @lua@param replacement c2.Message The replacement.
|
||||
* @exposed c2.Channel:replace_message
|
||||
*/
|
||||
void replace_message(const MessagePtrMut &message,
|
||||
const MessagePtrMut &replacement);
|
||||
/**
|
||||
* Replace a specific message with a different one.
|
||||
*
|
||||
* @lua@param message c2.Message The message to replace.
|
||||
* @lua@param replacement c2.Message The replacement.
|
||||
* @lua@param hint number A one-based index (from the start) where the message is probably located. This is checked first. Otherwise the behavior is identical to the overload without this parameter.
|
||||
* @exposed c2.Channel:replace_message
|
||||
*/
|
||||
void replace_message_hint(const MessagePtrMut &message,
|
||||
const MessagePtrMut &replacement, size_t hint);
|
||||
|
||||
/**
|
||||
* Replace a message at an index with a different one.
|
||||
*
|
||||
* @lua@param index number A one-based index (from the start) of the message to replace.
|
||||
* @lua@param replacement c2.Message The replacement.
|
||||
* @exposed c2.Channel:replace_message_at
|
||||
*/
|
||||
void replace_message_at(size_t index, const MessagePtrMut &replacement);
|
||||
|
||||
/**
|
||||
* Remove all messages in this channel.
|
||||
*
|
||||
* @exposed c2.Channel:clear_messages
|
||||
*/
|
||||
void clear_messages();
|
||||
|
||||
/**
|
||||
* Find a message by its ID.
|
||||
*
|
||||
* @lua@param id string
|
||||
* @lua@return c2.Message?
|
||||
* @exposed c2.Channel:find_message_by_id
|
||||
*/
|
||||
MessagePtrMut find_message_by_id(const QString &id);
|
||||
|
||||
/**
|
||||
* Check if the channel has any messages.
|
||||
*
|
||||
* @lua@return boolean
|
||||
* @exposed c2.Channel:has_messages
|
||||
*/
|
||||
bool has_messages();
|
||||
|
||||
/**
|
||||
* Count the number of messages in this channel.
|
||||
*
|
||||
* @lua@return number
|
||||
* @exposed c2.Channel:count_messages
|
||||
*/
|
||||
size_t count_messages();
|
||||
|
||||
/**
|
||||
* Returns true for twitch channels.
|
||||
* Compares the channel Type. Note that enum values aren't guaranteed, just
|
||||
|
||||
@@ -56,6 +56,14 @@ public:
|
||||
return this->buffer_.empty();
|
||||
}
|
||||
|
||||
/// Number of items in this container
|
||||
[[nodiscard]] size_t size() const
|
||||
{
|
||||
std::shared_lock lock(this->mutex_);
|
||||
|
||||
return this->buffer_.size();
|
||||
}
|
||||
|
||||
/// Value Accessors
|
||||
// Copies of values are returned so that references aren't invalidated
|
||||
|
||||
@@ -335,6 +343,18 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
[[nodiscard]] std::vector<U> lastNBy(size_t nItems, auto &&cb) const
|
||||
{
|
||||
std::shared_lock lock(this->mutex_);
|
||||
std::vector<U> vec;
|
||||
std::transform(
|
||||
this->buffer_.end() - std::min(nItems, this->buffer_.size()),
|
||||
this->buffer_.end(), std::back_inserter(vec),
|
||||
std::forward<decltype(cb)>(cb));
|
||||
return vec;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::vector<T> firstN(size_t nItems) const
|
||||
{
|
||||
std::shared_lock lock(this->mutex_);
|
||||
|
||||
Reference in New Issue
Block a user