feat: show restricted chats and suspicious treatment updates (#5056)

Co-authored-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
iProdigy
2023-12-31 04:44:55 -06:00
committed by GitHub
parent 69a54d944d
commit 036a5f3f21
15 changed files with 769 additions and 11 deletions
@@ -0,0 +1,104 @@
#include "providers/twitch/pubsubmessages/LowTrustUsers.hpp"
#include <QDateTime>
#include <QJsonArray>
namespace chatterino {
PubSubLowTrustUsersMessage::PubSubLowTrustUsersMessage(const QJsonObject &root)
: typeString(root.value("type").toString())
{
if (const auto oType =
magic_enum::enum_cast<Type>(this->typeString.toStdString());
oType.has_value())
{
this->type = oType.value();
}
auto data = root.value("data").toObject();
if (this->type == Type::UserMessage)
{
this->msgID = data.value("message_id").toString();
this->sentAt = data.value("sent_at").toString();
this->text =
data.value("message_content").toObject().value("text").toString();
// the rest of the data is within a nested object
data = data.value("low_trust_user").toObject();
const auto sender = data.value("sender").toObject();
this->suspiciousUserID = sender.value("user_id").toString();
this->suspiciousUserLogin = sender.value("login").toString();
this->suspiciousUserDisplayName =
sender.value("display_name").toString();
this->suspiciousUserColor =
QColor(sender.value("chat_color").toString());
std::vector<LowTrustUserChatBadge> badges;
for (const auto &badge : sender.value("badges").toArray())
{
badges.emplace_back(badge.toObject());
}
this->senderBadges = badges;
const auto sharedValue = data.value("shared_ban_channel_ids");
std::vector<QString> sharedIDs;
if (!sharedValue.isNull())
{
for (const auto &id : sharedValue.toArray())
{
sharedIDs.emplace_back(id.toString());
}
}
this->sharedBanChannelIDs = sharedIDs;
}
else
{
this->suspiciousUserID = data.value("target_user_id").toString();
this->suspiciousUserLogin = data.value("target_user").toString();
this->suspiciousUserDisplayName = this->suspiciousUserLogin;
}
this->channelID = data.value("channel_id").toString();
this->updatedAtString = data.value("updated_at").toString();
this->updatedAt = QDateTime::fromString(this->updatedAtString, Qt::ISODate)
.toLocalTime()
.toString("MMM d yyyy, h:mm ap");
const auto updatedBy = data.value("updated_by").toObject();
this->updatedByUserID = updatedBy.value("id").toString();
this->updatedByUserLogin = updatedBy.value("login").toString();
this->updatedByUserDisplayName = updatedBy.value("display_name").toString();
this->treatmentString = data.value("treatment").toString();
if (const auto oTreatment = magic_enum::enum_cast<Treatment>(
this->treatmentString.toStdString());
oTreatment.has_value())
{
this->treatment = oTreatment.value();
}
this->evasionEvaluationString =
data.value("ban_evasion_evaluation").toString();
if (const auto oEvaluation = magic_enum::enum_cast<EvasionEvaluation>(
this->evasionEvaluationString.toStdString());
oEvaluation.has_value())
{
this->evasionEvaluation = oEvaluation.value();
}
FlagsEnum<RestrictionType> restrictions;
for (const auto &rType : data.value("types").toArray())
{
if (const auto oRestriction = magic_enum::enum_cast<RestrictionType>(
rType.toString().toStdString());
oRestriction.has_value())
{
restrictions.set(oRestriction.value());
}
}
this->restrictionTypes = restrictions;
}
} // namespace chatterino
@@ -0,0 +1,255 @@
#pragma once
#include <common/FlagsEnum.hpp>
#include <magic_enum/magic_enum.hpp>
#include <QColor>
#include <QJsonObject>
#include <QString>
namespace chatterino {
struct LowTrustUserChatBadge {
QString id;
QString version;
explicit LowTrustUserChatBadge(const QJsonObject &obj)
: id(obj.value("id").toString())
, version(obj.value("version").toString())
{
}
};
struct PubSubLowTrustUsersMessage {
/**
* The type of low trust message update
*/
enum class Type {
/**
* An incoming message from someone marked as low trust
*/
UserMessage,
/**
* An incoming update about a user's low trust status
*/
TreatmentUpdate,
INVALID,
};
/**
* The treatment set for the suspicious user
*/
enum class Treatment {
NoTreatment,
ActiveMonitoring,
Restricted,
INVALID,
};
/**
* A ban evasion likelihood value (if any) that has been applied to the user
* automatically by Twitch
*/
enum class EvasionEvaluation {
UnknownEvader,
UnlikelyEvader,
LikelyEvader,
PossibleEvader,
INVALID,
};
/**
* Restriction type (if any) that apply to the suspicious user
*/
enum class RestrictionType : uint8_t {
UnknownType = 1 << 0,
ManuallyAdded = 1 << 1,
DetectedBanEvader = 1 << 2,
BannedInSharedChannel = 1 << 3,
INVALID = 1 << 4,
};
Type type = Type::INVALID;
Treatment treatment = Treatment::INVALID;
EvasionEvaluation evasionEvaluation = EvasionEvaluation::INVALID;
FlagsEnum<RestrictionType> restrictionTypes;
QString channelID;
QString suspiciousUserID;
QString suspiciousUserLogin;
QString suspiciousUserDisplayName;
QString updatedByUserID;
QString updatedByUserLogin;
QString updatedByUserDisplayName;
/**
* Formatted timestamp of when the treatment was last updated for the suspicious user
*/
QString updatedAt;
/**
* Plain text of the message sent.
* Only used for the UserMessage type.
*/
QString text;
/**
* ID of the message.
* Only used for the UserMessage type.
*/
QString msgID;
/**
* RFC3339 timestamp of when the message was sent.
* Only used for the UserMessage type.
*/
QString sentAt;
/**
* Color of the user who sent the message.
* Only used for the UserMessage type.
*/
QColor suspiciousUserColor;
/**
* A list of channel IDs where the suspicious user is also banned.
* Only used for the UserMessage type.
*/
std::vector<QString> sharedBanChannelIDs;
/**
* A list of badges of the user who sent the message.
* Only used for the UserMessage type.
*/
std::vector<LowTrustUserChatBadge> senderBadges;
/**
* Stores the string value of `type`
* Useful in case type shows up as invalid after being parsed
*/
QString typeString;
/**
* Stores the string value of `treatment`
* Useful in case treatment shows up as invalid after being parsed
*/
QString treatmentString;
/**
* Stores the string value of `ban_evasion_evaluation`
* Useful in case evasionEvaluation shows up as invalid after being parsed
*/
QString evasionEvaluationString;
/**
* Stores the string value of `updated_at`
* Useful in case formattedUpdatedAt doesn't parse correctly
*/
QString updatedAtString;
PubSubLowTrustUsersMessage() = default;
explicit PubSubLowTrustUsersMessage(const QJsonObject &root);
};
} // namespace chatterino
template <>
constexpr magic_enum::customize::customize_t magic_enum::customize::enum_name<
chatterino::PubSubLowTrustUsersMessage::Type>(
chatterino::PubSubLowTrustUsersMessage::Type value) noexcept
{
switch (value)
{
case chatterino::PubSubLowTrustUsersMessage::Type::UserMessage:
return "low_trust_user_new_message";
case chatterino::PubSubLowTrustUsersMessage::Type::TreatmentUpdate:
return "low_trust_user_treatment_update";
default:
return default_tag;
}
}
template <>
constexpr magic_enum::customize::customize_t magic_enum::customize::enum_name<
chatterino::PubSubLowTrustUsersMessage::Treatment>(
chatterino::PubSubLowTrustUsersMessage::Treatment value) noexcept
{
using Treatment = chatterino::PubSubLowTrustUsersMessage::Treatment;
switch (value)
{
case Treatment::NoTreatment:
return "NO_TREATMENT";
case Treatment::ActiveMonitoring:
return "ACTIVE_MONITORING";
case Treatment::Restricted:
return "RESTRICTED";
default:
return default_tag;
}
}
template <>
constexpr magic_enum::customize::customize_t magic_enum::customize::enum_name<
chatterino::PubSubLowTrustUsersMessage::EvasionEvaluation>(
chatterino::PubSubLowTrustUsersMessage::EvasionEvaluation value) noexcept
{
using EvasionEvaluation =
chatterino::PubSubLowTrustUsersMessage::EvasionEvaluation;
switch (value)
{
case EvasionEvaluation::UnknownEvader:
return "UNKNOWN_EVADER";
case EvasionEvaluation::UnlikelyEvader:
return "UNLIKELY_EVADER";
case EvasionEvaluation::LikelyEvader:
return "LIKELY_EVADER";
case EvasionEvaluation::PossibleEvader:
return "POSSIBLE_EVADER";
default:
return default_tag;
}
}
template <>
constexpr magic_enum::customize::customize_t magic_enum::customize::enum_name<
chatterino::PubSubLowTrustUsersMessage::RestrictionType>(
chatterino::PubSubLowTrustUsersMessage::RestrictionType value) noexcept
{
using RestrictionType =
chatterino::PubSubLowTrustUsersMessage::RestrictionType;
switch (value)
{
case RestrictionType::UnknownType:
return "UNKNOWN_TYPE";
case RestrictionType::ManuallyAdded:
return "MANUALLY_ADDED";
case RestrictionType::DetectedBanEvader:
return "DETECTED_BAN_EVADER";
case RestrictionType::BannedInSharedChannel:
return "BANNED_IN_SHARED_CHANNEL";
default:
return default_tag;
}
}