feat(eventsub): implement (shared-chat-)ban (#5985)

This commit is contained in:
nerix
2025-02-25 21:13:05 +01:00
committed by GitHub
parent aee5f1a54d
commit 044dc69aa6
18 changed files with 1060 additions and 331 deletions
+1 -7
View File
@@ -55,12 +55,6 @@ def _is_trivially_copyable(type: clang.cindex.Type) -> bool:
return _is_chrono_like_type(type)
def _has_no_fields(type: clang.cindex.Type) -> bool:
for _ in type.get_fields():
return False
return True
@dataclass
class VariantType:
name: str
@@ -179,7 +173,7 @@ class Member:
VariantType(
name=name,
trivial=_is_trivially_copyable(inner),
empty=_has_no_fields(inner),
empty=inner.get_size() <= 1,
)
)
+7 -1
View File
@@ -1,6 +1,6 @@
from __future__ import annotations
from typing import List
from typing import List, Optional
import logging
@@ -20,6 +20,7 @@ class Struct:
self.comment_commands = CommentCommands()
self.inner_root: str = ""
self.namespace = namespace
self.base: Optional[str] = None
@property
def full_name(self) -> str:
@@ -48,3 +49,8 @@ class Struct:
def apply_comment_commands(self, comment_commands: CommentCommands) -> None:
self.inner_root = comment_commands.inner_root
def validate(self) -> None:
assert not (self.base and self.members), (
f"Unsupported: Struct {self.name} has both a base class as well as additional members"
)
@@ -1,5 +1,5 @@
boost::json::result_for<{{struct.full_name}}, boost::json::value>::type tag_invoke(
boost::json::try_value_to_tag<{{struct.full_name}}> /* tag */, const boost::json::value &{%- if struct.members|length -%}jvRoot{%- else -%}/* jvRoot */{%- endif -%})
boost::json::try_value_to_tag<{{struct.full_name}}> /* tag */, const boost::json::value &{%- if struct.members|length or struct.base -%}jvRoot{%- else -%}/* jvRoot */{%- endif -%})
{
{% if struct.inner_root %}
if (!jvRoot.is_object())
@@ -24,6 +24,12 @@ boost::json::result_for<{{struct.full_name}}, boost::json::value>::type tag_invo
EVENTSUB_BAIL_HERE(error::Kind::ExpectedObject);
}
const auto &root = jvRoot.get_object();
{% elif struct.base %}
auto base = boost::json::try_value_to<{{struct.base}}>(jvRoot);
if (base.has_error())
{
return base.error();
}
{% endif %}
{% for field in struct.members %}
@@ -56,6 +62,9 @@ boost::json::result_for<{{struct.full_name}}, boost::json::value>::type tag_invo
{%- elif field.member_type == MemberType.VARIANT -%}
{% include 'initializer-variant.tmpl' indent content %}
{%- endif -%}
{% endfor %}
{% endfor -%}
{%- if struct.base %}
std::move(*base)
{% endif -%}
};
}
+6
View File
@@ -36,6 +36,7 @@ class Walker:
for child in node.get_children():
self.handle_node(child, new_struct, None)
new_struct.validate()
self.structs.append(new_struct)
return True
@@ -83,6 +84,11 @@ class Walker:
self.namespace = self.namespace[:-1]
return True
case CursorKind.CXX_BASE_SPECIFIER:
assert struct
struct.base = node.type.spelling
return False
case CursorKind.FUNCTION_DECL:
# Ignore function declarations
pass
@@ -161,13 +161,11 @@ struct Unmod {
struct Ban {
static constexpr std::string_view TAG = "ban";
static constexpr std::string_view FIELD = "ban";
std::string userID;
std::string userLogin;
std::string userName;
// TODO: Verify that we handle null here
std::string reason;
String userID;
String userLogin;
String userName;
String reason;
};
struct SharedChatBan : public Ban {
static constexpr std::string_view TAG = "shared_chat_ban";
@@ -179,7 +177,6 @@ struct SharedChatBan : public Ban {
struct Unban {
static constexpr std::string_view TAG = "unban";
static constexpr std::string_view FIELD = "unban";
std::string userID;
std::string userLogin;
@@ -199,7 +196,6 @@ struct SharedChatUnban : public Ban {
struct Timeout {
static constexpr std::string_view TAG = "timeout";
static constexpr std::string_view FIELD = "timeout";
std::string userID;
std::string userLogin;
@@ -219,7 +215,6 @@ struct SharedChatTimeout : public Ban {
struct Untimeout {
static constexpr std::string_view TAG = "untimeout";
static constexpr std::string_view FIELD = "untimeout";
std::string userID;
std::string userLogin;
@@ -261,7 +256,6 @@ struct Unraid {
struct Delete {
static constexpr std::string_view TAG = "delete";
static constexpr std::string_view FIELD = "delete";
std::string userID;
std::string userLogin;
@@ -325,7 +325,7 @@ boost::json::result_for<Ban, boost::json::value>::type tag_invoke(
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto userID = boost::json::try_value_to<std::string>(*jvuserID);
auto userID = boost::json::try_value_to<String>(*jvuserID);
if (userID.has_error())
{
@@ -338,7 +338,7 @@ boost::json::result_for<Ban, boost::json::value>::type tag_invoke(
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto userLogin = boost::json::try_value_to<std::string>(*jvuserLogin);
auto userLogin = boost::json::try_value_to<String>(*jvuserLogin);
if (userLogin.has_error())
{
@@ -351,7 +351,7 @@ boost::json::result_for<Ban, boost::json::value>::type tag_invoke(
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto userName = boost::json::try_value_to<std::string>(*jvuserName);
auto userName = boost::json::try_value_to<String>(*jvuserName);
if (userName.has_error())
{
@@ -364,7 +364,7 @@ boost::json::result_for<Ban, boost::json::value>::type tag_invoke(
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto reason = boost::json::try_value_to<std::string>(*jvreason);
auto reason = boost::json::try_value_to<String>(*jvreason);
if (reason.has_error())
{
@@ -381,9 +381,15 @@ boost::json::result_for<Ban, boost::json::value>::type tag_invoke(
boost::json::result_for<SharedChatBan, boost::json::value>::type tag_invoke(
boost::json::try_value_to_tag<SharedChatBan> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return SharedChatBan{};
auto base = boost::json::try_value_to<Ban>(jvRoot);
if (base.has_error())
{
return base.error();
}
return SharedChatBan{std::move(*base)};
}
boost::json::result_for<Unban, boost::json::value>::type tag_invoke(
@@ -444,9 +450,15 @@ boost::json::result_for<Unban, boost::json::value>::type tag_invoke(
boost::json::result_for<SharedChatUnban, boost::json::value>::type tag_invoke(
boost::json::try_value_to_tag<SharedChatUnban> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return SharedChatUnban{};
auto base = boost::json::try_value_to<Ban>(jvRoot);
if (base.has_error())
{
return base.error();
}
return SharedChatUnban{std::move(*base)};
}
boost::json::result_for<Timeout, boost::json::value>::type tag_invoke(
@@ -535,9 +547,15 @@ boost::json::result_for<Timeout, boost::json::value>::type tag_invoke(
boost::json::result_for<SharedChatTimeout, boost::json::value>::type tag_invoke(
boost::json::try_value_to_tag<SharedChatTimeout> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return SharedChatTimeout{};
auto base = boost::json::try_value_to<Ban>(jvRoot);
if (base.has_error())
{
return base.error();
}
return SharedChatTimeout{std::move(*base)};
}
boost::json::result_for<Untimeout, boost::json::value>::type tag_invoke(
@@ -598,9 +616,15 @@ boost::json::result_for<Untimeout, boost::json::value>::type tag_invoke(
boost::json::result_for<SharedChatUntimeout, boost::json::value>::type
tag_invoke(boost::json::try_value_to_tag<SharedChatUntimeout> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return SharedChatUntimeout{};
auto base = boost::json::try_value_to<Ban>(jvRoot);
if (base.has_error())
{
return base.error();
}
return SharedChatUntimeout{std::move(*base)};
}
boost::json::result_for<Raid, boost::json::value>::type tag_invoke(
@@ -817,9 +841,15 @@ boost::json::result_for<Delete, boost::json::value>::type tag_invoke(
boost::json::result_for<SharedChatDelete, boost::json::value>::type tag_invoke(
boost::json::try_value_to_tag<SharedChatDelete> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return SharedChatDelete{};
auto base = boost::json::try_value_to<Ban>(jvRoot);
if (base.has_error())
{
return base.error();
}
return SharedChatDelete{std::move(*base)};
}
boost::json::result_for<AutomodTerms, boost::json::value>::type tag_invoke(
@@ -898,30 +928,54 @@ boost::json::result_for<AutomodTerms, boost::json::value>::type tag_invoke(
boost::json::result_for<AddBlockedTerm, boost::json::value>::type tag_invoke(
boost::json::try_value_to_tag<AddBlockedTerm> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return AddBlockedTerm{};
auto base = boost::json::try_value_to<AutomodTerms>(jvRoot);
if (base.has_error())
{
return base.error();
}
return AddBlockedTerm{std::move(*base)};
}
boost::json::result_for<AddPermittedTerm, boost::json::value>::type tag_invoke(
boost::json::try_value_to_tag<AddPermittedTerm> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return AddPermittedTerm{};
auto base = boost::json::try_value_to<AutomodTerms>(jvRoot);
if (base.has_error())
{
return base.error();
}
return AddPermittedTerm{std::move(*base)};
}
boost::json::result_for<RemoveBlockedTerm, boost::json::value>::type tag_invoke(
boost::json::try_value_to_tag<RemoveBlockedTerm> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return RemoveBlockedTerm{};
auto base = boost::json::try_value_to<AutomodTerms>(jvRoot);
if (base.has_error())
{
return base.error();
}
return RemoveBlockedTerm{std::move(*base)};
}
boost::json::result_for<RemovePermittedTerm, boost::json::value>::type
tag_invoke(boost::json::try_value_to_tag<RemovePermittedTerm> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return RemovePermittedTerm{};
auto base = boost::json::try_value_to<AutomodTerms>(jvRoot);
if (base.has_error())
{
return base.error();
}
return RemovePermittedTerm{std::move(*base)};
}
boost::json::result_for<UnbanRequest, boost::json::value>::type tag_invoke(
@@ -1013,16 +1067,28 @@ boost::json::result_for<UnbanRequest, boost::json::value>::type tag_invoke(
boost::json::result_for<ApproveUnbanRequest, boost::json::value>::type
tag_invoke(boost::json::try_value_to_tag<ApproveUnbanRequest> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return ApproveUnbanRequest{};
auto base = boost::json::try_value_to<UnbanRequest>(jvRoot);
if (base.has_error())
{
return base.error();
}
return ApproveUnbanRequest{std::move(*base)};
}
boost::json::result_for<DenyUnbanRequest, boost::json::value>::type tag_invoke(
boost::json::try_value_to_tag<DenyUnbanRequest> /* tag */,
const boost::json::value & /* jvRoot */)
const boost::json::value &jvRoot)
{
return DenyUnbanRequest{};
auto base = boost::json::try_value_to<UnbanRequest>(jvRoot);
if (base.has_error())
{
return base.error();
}
return DenyUnbanRequest{std::move(*base)};
}
boost::json::result_for<Warn, boost::json::value>::type tag_invoke(
@@ -1519,19 +1585,70 @@ boost::json::result_for<Event, boost::json::value>::type tag_invoke(
}
else if (actionTag == AddBlockedTerm::TAG)
{
action.emplace<AddBlockedTerm>();
const auto *actionVal =
root.if_contains(detail::fieldFor<AddBlockedTerm>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionAddBlockedTerm =
boost::json::try_value_to<AddBlockedTerm>(*actionVal);
if (actionAddBlockedTerm.has_error())
{
return actionAddBlockedTerm.error();
}
action.emplace<AddBlockedTerm>(std::move(actionAddBlockedTerm.value()));
}
else if (actionTag == AddPermittedTerm::TAG)
{
action.emplace<AddPermittedTerm>();
const auto *actionVal =
root.if_contains(detail::fieldFor<AddPermittedTerm>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionAddPermittedTerm =
boost::json::try_value_to<AddPermittedTerm>(*actionVal);
if (actionAddPermittedTerm.has_error())
{
return actionAddPermittedTerm.error();
}
action.emplace<AddPermittedTerm>(
std::move(actionAddPermittedTerm.value()));
}
else if (actionTag == RemoveBlockedTerm::TAG)
{
action.emplace<RemoveBlockedTerm>();
const auto *actionVal =
root.if_contains(detail::fieldFor<RemoveBlockedTerm>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionRemoveBlockedTerm =
boost::json::try_value_to<RemoveBlockedTerm>(*actionVal);
if (actionRemoveBlockedTerm.has_error())
{
return actionRemoveBlockedTerm.error();
}
action.emplace<RemoveBlockedTerm>(
std::move(actionRemoveBlockedTerm.value()));
}
else if (actionTag == RemovePermittedTerm::TAG)
{
action.emplace<RemovePermittedTerm>();
const auto *actionVal =
root.if_contains(detail::fieldFor<RemovePermittedTerm>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionRemovePermittedTerm =
boost::json::try_value_to<RemovePermittedTerm>(*actionVal);
if (actionRemovePermittedTerm.has_error())
{
return actionRemovePermittedTerm.error();
}
action.emplace<RemovePermittedTerm>(
std::move(actionRemovePermittedTerm.value()));
}
else if (actionTag == Mod::TAG)
{
@@ -1563,11 +1680,37 @@ boost::json::result_for<Event, boost::json::value>::type tag_invoke(
}
else if (actionTag == ApproveUnbanRequest::TAG)
{
action.emplace<ApproveUnbanRequest>();
const auto *actionVal =
root.if_contains(detail::fieldFor<ApproveUnbanRequest>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionApproveUnbanRequest =
boost::json::try_value_to<ApproveUnbanRequest>(*actionVal);
if (actionApproveUnbanRequest.has_error())
{
return actionApproveUnbanRequest.error();
}
action.emplace<ApproveUnbanRequest>(
std::move(actionApproveUnbanRequest.value()));
}
else if (actionTag == DenyUnbanRequest::TAG)
{
action.emplace<DenyUnbanRequest>();
const auto *actionVal =
root.if_contains(detail::fieldFor<DenyUnbanRequest>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionDenyUnbanRequest =
boost::json::try_value_to<DenyUnbanRequest>(*actionVal);
if (actionDenyUnbanRequest.has_error())
{
return actionDenyUnbanRequest.error();
}
action.emplace<DenyUnbanRequest>(
std::move(actionDenyUnbanRequest.value()));
}
else if (actionTag == Warn::TAG)
{
@@ -1585,23 +1728,87 @@ boost::json::result_for<Event, boost::json::value>::type tag_invoke(
}
else if (actionTag == SharedChatBan::TAG)
{
action.emplace<SharedChatBan>();
const auto *actionVal =
root.if_contains(detail::fieldFor<SharedChatBan>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionSharedChatBan =
boost::json::try_value_to<SharedChatBan>(*actionVal);
if (actionSharedChatBan.has_error())
{
return actionSharedChatBan.error();
}
action.emplace<SharedChatBan>(std::move(actionSharedChatBan.value()));
}
else if (actionTag == SharedChatTimeout::TAG)
{
action.emplace<SharedChatTimeout>();
const auto *actionVal =
root.if_contains(detail::fieldFor<SharedChatTimeout>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionSharedChatTimeout =
boost::json::try_value_to<SharedChatTimeout>(*actionVal);
if (actionSharedChatTimeout.has_error())
{
return actionSharedChatTimeout.error();
}
action.emplace<SharedChatTimeout>(
std::move(actionSharedChatTimeout.value()));
}
else if (actionTag == SharedChatUnban::TAG)
{
action.emplace<SharedChatUnban>();
const auto *actionVal =
root.if_contains(detail::fieldFor<SharedChatUnban>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionSharedChatUnban =
boost::json::try_value_to<SharedChatUnban>(*actionVal);
if (actionSharedChatUnban.has_error())
{
return actionSharedChatUnban.error();
}
action.emplace<SharedChatUnban>(
std::move(actionSharedChatUnban.value()));
}
else if (actionTag == SharedChatUntimeout::TAG)
{
action.emplace<SharedChatUntimeout>();
const auto *actionVal =
root.if_contains(detail::fieldFor<SharedChatUntimeout>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionSharedChatUntimeout =
boost::json::try_value_to<SharedChatUntimeout>(*actionVal);
if (actionSharedChatUntimeout.has_error())
{
return actionSharedChatUntimeout.error();
}
action.emplace<SharedChatUntimeout>(
std::move(actionSharedChatUntimeout.value()));
}
else if (actionTag == SharedChatDelete::TAG)
{
action.emplace<SharedChatDelete>();
const auto *actionVal =
root.if_contains(detail::fieldFor<SharedChatDelete>());
if (!actionVal)
{
EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
}
auto actionSharedChatDelete =
boost::json::try_value_to<SharedChatDelete>(*actionVal);
if (actionSharedChatDelete.has_error())
{
return actionSharedChatDelete.error();
}
action.emplace<SharedChatDelete>(
std::move(actionSharedChatDelete.value()));
}
else
{