Skip to content

Commit fc853aa

Browse files
committed
implement eventsub automod
1 parent b3d1961 commit fc853aa

File tree

3 files changed

+275
-2
lines changed

3 files changed

+275
-2
lines changed

twitchio/ext/eventsub/models.py

Lines changed: 218 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import hashlib
55
import logging
66
from enum import Enum
7-
from typing import Dict, TYPE_CHECKING, Optional, Type, Union, Tuple, List, overload
7+
from typing import Any, Dict, TYPE_CHECKING, Optional, Type, Union, Tuple, List, overload
88
from typing_extensions import Literal
99

1010
from aiohttp import web
@@ -1677,6 +1677,214 @@ def __init__(self, client: EventSubClient, data: dict):
16771677
self.created_at: datetime.datetime = _parse_datetime(data["created_at"])
16781678

16791679

1680+
class AutomodMessageHoldData(EventData):
1681+
"""
1682+
Represents a message being held by automod for manual review.
1683+
1684+
Attributes
1685+
------------
1686+
message_id: :class:`str`
1687+
The ID of the message.
1688+
message_content: :class:`str`
1689+
The contents of the message
1690+
broadcaster: :class:`PartialUser`
1691+
The broadcaster from which the message was held.
1692+
user: :class:`PartialUser`
1693+
The user that sent the message.
1694+
level: :class:`int`
1695+
The level of alarm raised for this message.
1696+
category: :class:`str`
1697+
The category of alarm that was raised for this message.
1698+
created_at: :class:`datetime.datetime`
1699+
When this message was held.
1700+
message_fragments: :class:`dict`
1701+
The fragments of this message. This includes things such as emotes and cheermotes. An example from twitch is provided:
1702+
1703+
.. code:: json
1704+
1705+
{
1706+
"emotes": [
1707+
{
1708+
"text": "badtextemote1",
1709+
"id": "emote-123",
1710+
"set-id": "set-emote-1"
1711+
},
1712+
{
1713+
"text": "badtextemote2",
1714+
"id": "emote-234",
1715+
"set-id": "set-emote-2"
1716+
}
1717+
],
1718+
"cheermotes": [
1719+
{
1720+
"text": "badtextcheermote1",
1721+
"amount": 1000,
1722+
"prefix": "prefix",
1723+
"tier": 1
1724+
}
1725+
]
1726+
}
1727+
"""
1728+
1729+
__slots__ = ("message_id", "message_content", "broadcaster", "user", "level", "category", "message_fragments", "created_at")
1730+
1731+
def __init__(self, client: EventSubClient, data: dict):
1732+
self.message_id: str = data["message_id"]
1733+
self.message_content: str = data["message"]
1734+
self.message_fragments: Dict[str, Dict[str, Any]] = data["fragments"]
1735+
self.broadcaster: PartialUser = _transform_user(client, data, "broadcaster_user")
1736+
self.user: PartialUser = _transform_user(client, data, "user")
1737+
self.level: int = data["level"]
1738+
self.category: str = data["category"]
1739+
self.created_at: datetime.datetime = _parse_datetime(data["held_at"])
1740+
1741+
1742+
class AutomodMessageUpdateData(EventData):
1743+
"""
1744+
Represents a message that was updated by a moderator in the automod queue.
1745+
1746+
Attributes
1747+
------------
1748+
message_id: :class:`str`
1749+
The ID of the message.
1750+
message_content: :class:`str`
1751+
The contents of the message
1752+
broadcaster: :class:`PartialUser`
1753+
The broadcaster from which the message was held.
1754+
user: :class:`PartialUser`
1755+
The user that sent the message.
1756+
moderator: :class:`PartialUser`
1757+
The moderator that updated the message status.
1758+
status: :class:`str`
1759+
The new status of the message. Typically one of ``approved`` or ``denied``.
1760+
level: :class:`int`
1761+
The level of alarm raised for this message.
1762+
category: :class:`str`
1763+
The category of alarm that was raised for this message.
1764+
created_at: :class:`datetime.datetime`
1765+
When this message was held.
1766+
message_fragments: :class:`dict`
1767+
The fragments of this message. This includes things such as emotes and cheermotes. An example from twitch is provided:
1768+
1769+
.. code:: json
1770+
1771+
{
1772+
"emotes": [
1773+
{
1774+
"text": "badtextemote1",
1775+
"id": "emote-123",
1776+
"set-id": "set-emote-1"
1777+
},
1778+
{
1779+
"text": "badtextemote2",
1780+
"id": "emote-234",
1781+
"set-id": "set-emote-2"
1782+
}
1783+
],
1784+
"cheermotes": [
1785+
{
1786+
"text": "badtextcheermote1",
1787+
"amount": 1000,
1788+
"prefix": "prefix",
1789+
"tier": 1
1790+
}
1791+
]
1792+
}
1793+
"""
1794+
1795+
__slots__ = ("message_id", "message_content", "broadcaster", "user", "moderator", "level", "category", "message_fragments", "created_at", "status")
1796+
1797+
def __init__(self, client: EventSubClient, data: dict):
1798+
self.message_id: str = data["message_id"]
1799+
self.message_content: str = data["message"]
1800+
self.message_fragments: Dict[str, Dict[str, Any]] = data["fragments"]
1801+
self.broadcaster: PartialUser = _transform_user(client, data, "broadcaster_user")
1802+
self.moderator: PartialUser = _transform_user(client, data, "moderator_user")
1803+
self.user: PartialUser = _transform_user(client, data, "user")
1804+
self.level: int = data["level"]
1805+
self.category: str = data["category"]
1806+
self.created_at: datetime.datetime = _parse_datetime(data["held_at"])
1807+
self.status: str = data["status"]
1808+
1809+
1810+
class AutomodSettingsUpdateData(EventData):
1811+
"""
1812+
Represents a channels automod settings being updated.
1813+
1814+
Attributes
1815+
------------
1816+
broadcaster: :class:`PartialUser`
1817+
The broadcaster for which the settings were updated.
1818+
moderator: :class:`PartialUser`
1819+
The moderator that updated the settings.
1820+
overall :class:`int` | ``None``
1821+
The overall level of automod aggressiveness.
1822+
disability: :class:`int` | ``None``
1823+
The aggression towards disability.
1824+
aggression: :class:`int` | ``None``
1825+
The aggression towards aggressive users.
1826+
sex: :class:`int` | ``None``
1827+
The aggression towards sexuality/gender.
1828+
misogyny: :class:`int` | ``None``
1829+
The aggression towards misogyny.
1830+
bullying: :class:`int` | ``None``
1831+
The aggression towards bullying.
1832+
swearing: :class:`int` | ``None``
1833+
The aggression towards cursing/language.
1834+
race_religion: :class:`int` | ``None``
1835+
The aggression towards race, ethnicity, and religion.
1836+
sexual_terms: :class:`int` | ``None``
1837+
The aggression towards sexual terms/references.
1838+
"""
1839+
1840+
__slots__ = ("broadcaster", "moderator", "overall", "disability", "aggression", "sex", "misogyny", "bullying", "swearing", "race_religion", "sexual_terms")
1841+
1842+
def __init__(self, client: EventSubClient, data: dict):
1843+
self.broadcaster: PartialUser = _transform_user(client, data, "broadcaster_user")
1844+
self.moderator: PartialUser = _transform_user(client, data, "moderator_user")
1845+
self.overall: Optional[int] = data["overall"]
1846+
self.disability: Optional[int] = data["disability"]
1847+
self.aggression: Optional[int] = data["aggression"]
1848+
self.sex: Optional[int] = data["sex"]
1849+
self.misogyny: Optional[int] = data["misogyny"]
1850+
self.bullying: Optional[int] = data["bullying"]
1851+
self.swearing: Optional[int] = data["swearing"]
1852+
self.race_religion: Optional[int] = data["race_ethnicity_or_religion"]
1853+
self.sexual_terms: Optional[int] = data["sex_based_terms"]
1854+
1855+
1856+
class AutomodTermsUpdateData(EventData):
1857+
"""
1858+
Represents a channels automod terms being updated.
1859+
1860+
.. note::
1861+
1862+
Private terms are not sent.
1863+
1864+
Attributes
1865+
-----------
1866+
broadcaster: :class:`PartialUser`
1867+
The broadcaster for which the terms were updated.
1868+
moderator: :class:`PartialUser`
1869+
The moderator who updated the terms.
1870+
action: :class:`str`
1871+
The action type.
1872+
from_automod: :class:`bool`
1873+
Whether the action was taken by automod.
1874+
terms: List[:class:`str`]
1875+
The terms that were applied.
1876+
"""
1877+
1878+
__slots__ = ("broadcaster", "moderator", "action", "from_automod", "terms")
1879+
1880+
def __init__(self, client: EventSubClient, data: dict):
1881+
self.broadcaster: PartialUser = _transform_user(client, data, "broadcaster_user")
1882+
self.moderator: PartialUser = _transform_user(client, data, "moderator_user")
1883+
self.action: str = data["action"]
1884+
self.from_automod: bool = data["from_automod"]
1885+
self.terms: List[str] = data["terms"]
1886+
1887+
16801888
_DataType = Union[
16811889
ChannelBanData,
16821890
ChannelUnbanData,
@@ -1712,6 +1920,10 @@ def __init__(self, client: EventSubClient, data: dict):
17121920
ChannelCharityDonationData,
17131921
ChannelUnbanRequestCreateData,
17141922
ChannelUnbanRequestResolveData,
1923+
AutomodMessageHoldData,
1924+
AutomodMessageUpdateData,
1925+
AutomodSettingsUpdateData,
1926+
AutomodTermsUpdateData
17151927
]
17161928

17171929

@@ -1726,6 +1938,11 @@ class _SubscriptionTypes(metaclass=_SubTypesMeta):
17261938
_type_map: Dict[str, Type[_DataType]]
17271939
_name_map: Dict[str, str]
17281940

1941+
automod_message_hold = "automod.message.hold", 1, AutomodMessageHoldData
1942+
automod_message_update = "automod.message.update", 1, AutomodMessageUpdateData
1943+
automod_settings_update = "automod.settings.update", 1, AutomodSettingsUpdateData
1944+
automod_terms_update = "automod.terms.update", 1, AutomodTermsUpdateData
1945+
17291946
follow = "channel.follow", 1, ChannelFollowData
17301947
followV2 = "channel.follow", 2, ChannelFollowData
17311948
subscription = "channel.subscribe", 1, ChannelSubscribeData

twitchio/ext/eventsub/server.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,35 @@ def subscribe_channel_unban_request_resolve(
289289
return self._subscribe_with_broadcaster_moderator(
290290
models.SubscriptionTypes.unban_request_resolve, broadcaster, moderator
291291
)
292-
292+
293+
def subscribe_automod_message_hold(
294+
self, broadcaster: Union[PartialUser, str, int], moderator: Union[PartialUser, str, int]
295+
):
296+
return self._subscribe_with_broadcaster_moderator(
297+
models.SubscriptionTypes.automod_message_hold, broadcaster, moderator
298+
)
299+
300+
def subscribe_automod_message_update(
301+
self, broadcaster: Union[PartialUser, str, int], moderator: Union[PartialUser, str, int]
302+
):
303+
return self._subscribe_with_broadcaster_moderator(
304+
models.SubscriptionTypes.automod_message_update, broadcaster, moderator
305+
)
306+
307+
def subscribe_automod_settings_update(
308+
self, broadcaster: Union[PartialUser, str, int], moderator: Union[PartialUser, str, int]
309+
):
310+
return self._subscribe_with_broadcaster_moderator(
311+
models.SubscriptionTypes.automod_settings_update, broadcaster, moderator
312+
)
313+
314+
def subscribe_automod_terms_update(
315+
self, broadcaster: Union[PartialUser, str, int], moderator: Union[PartialUser, str, int]
316+
):
317+
return self._subscribe_with_broadcaster_moderator(
318+
models.SubscriptionTypes.automod_terms_update, broadcaster, moderator
319+
)
320+
293321
def subscribe_channel_charity_donate(self, broadcaster: Union[PartialUser, str, int]):
294322
return self._subscribe_with_broadcaster(models.SubscriptionTypes.channel_charity_donate, broadcaster)
295323

twitchio/ext/eventsub/websocket.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,3 +527,31 @@ async def subscribe_channel_unban_request_resolve(
527527
await self._subscribe_with_broadcaster_moderator(
528528
models.SubscriptionTypes.unban_request_resolve, broadcaster, moderator, token
529529
)
530+
531+
async def subscribe_automod_message_hold(
532+
self, broadcaster: Union[PartialUser, str, int], moderator: Union[PartialUser, str, int], token: str
533+
):
534+
await self._subscribe_with_broadcaster_moderator(
535+
models.SubscriptionTypes.automod_message_hold, broadcaster, moderator, token
536+
)
537+
538+
async def subscribe_automod_message_update(
539+
self, broadcaster: Union[PartialUser, str, int], moderator: Union[PartialUser, str, int], token: str
540+
):
541+
await self._subscribe_with_broadcaster_moderator(
542+
models.SubscriptionTypes.automod_message_update, broadcaster, moderator, token
543+
)
544+
545+
async def subscribe_automod_settings_update(
546+
self, broadcaster: Union[PartialUser, str, int], moderator: Union[PartialUser, str, int], token: str
547+
):
548+
await self._subscribe_with_broadcaster_moderator(
549+
models.SubscriptionTypes.automod_settings_update, broadcaster, moderator, token
550+
)
551+
552+
async def subscribe_automod_terms_update(
553+
self, broadcaster: Union[PartialUser, str, int], moderator: Union[PartialUser, str, int], token: str
554+
):
555+
await self._subscribe_with_broadcaster_moderator(
556+
models.SubscriptionTypes.automod_terms_update, broadcaster, moderator, token
557+
)

0 commit comments

Comments
 (0)