Add reward redemption

This commit is contained in:
2025-03-18 17:51:59 +01:00
parent 74acf4596a
commit 08704c6529
5 changed files with 169 additions and 66 deletions

View File

@@ -6,7 +6,7 @@ from twitchAPI.object.eventsub import ChannelChatMessageEvent
from httpx import AsyncClient from httpx import AsyncClient
from core.config import config from core.config import config
from .twitch.authorize import authorize from .twitch.authorize import authorize, Twitch
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -139,9 +139,8 @@ async def get_completion(messages: list[dict]) -> str:
class MessagesProc: class MessagesProc:
IGNORED_USER_LOGINS = [ FULL_IGNORED_USER_LOGINS = [
"jeetbot", "jeetbot",
"kurbezz",
] ]
MESSAGE_LIMIT = 1000 MESSAGE_LIMIT = 1000
@@ -172,9 +171,7 @@ class MessagesProc:
return [m for m in cls.MESSAGE_HISTORY if m["id"] == message_id] return [m for m in cls.MESSAGE_HISTORY if m["id"] == message_id]
@classmethod @classmethod
async def on_message(cls, event: MessageEvent): async def _update_history(cls, event: MessageEvent):
logging.info(f"Received message: {event}")
cls.update_message_history( cls.update_message_history(
id=event.message_id, id=event.message_id,
text=event.message.text, text=event.message.text,
@@ -182,11 +179,8 @@ class MessagesProc:
thread_id=event.reply.thread_message_id if event.reply is not None else None thread_id=event.reply.thread_message_id if event.reply is not None else None
) )
if event.chatter_user_name == "pahangor": @classmethod
return async def _goida(cls, twitch: Twitch, event: MessageEvent):
twitch = await authorize()
if "гойда" in event.message.text.lower(): if "гойда" in event.message.text.lower():
await twitch.send_chat_message( await twitch.send_chat_message(
event.broadcaster_user_id, event.broadcaster_user_id,
@@ -195,7 +189,11 @@ class MessagesProc:
reply_parent_message_id=event.message_id reply_parent_message_id=event.message_id
) )
if "lasqexx" in event.chatter_user_login: @classmethod
async def _lasqexx(cls, twitch: Twitch, event: MessageEvent):
if "lasqexx" not in event.chatter_user_login:
return
if "здароу" in event.message.text.lower(): if "здароу" in event.message.text.lower():
await twitch.send_chat_message( await twitch.send_chat_message(
event.broadcaster_user_id, event.broadcaster_user_id,
@@ -203,6 +201,7 @@ class MessagesProc:
"Здароу, давай иди уже", "Здароу, давай иди уже",
reply_parent_message_id=event.message_id reply_parent_message_id=event.message_id
) )
return
if "сосал?" in event.message.text.lower(): if "сосал?" in event.message.text.lower():
await twitch.send_chat_message( await twitch.send_chat_message(
@@ -211,6 +210,7 @@ class MessagesProc:
"А ты? Иди уже", "А ты? Иди уже",
reply_parent_message_id=event.message_id reply_parent_message_id=event.message_id
) )
return
if "лан я пошёл" in event.message.text.lower(): if "лан я пошёл" in event.message.text.lower():
await twitch.send_chat_message( await twitch.send_chat_message(
@@ -219,8 +219,13 @@ class MessagesProc:
"да да, иди уже", "да да, иди уже",
reply_parent_message_id=event.message_id reply_parent_message_id=event.message_id
) )
return
@classmethod
async def _ask_ai(cls, twitch: Twitch, event: MessageEvent):
if not event.message.text.lower().startswith("!ai"):
return
if event.message.text.lower().startswith("!ai"):
try: try:
messages = cls.get_message_history_with_thread( messages = cls.get_message_history_with_thread(
event.message_id, event.message_id,
@@ -255,7 +260,9 @@ class MessagesProc:
reply_parent_message_id=event.message_id reply_parent_message_id=event.message_id
) )
if event.chatter_user_login in cls.IGNORED_USER_LOGINS: @classmethod
async def _kurbezz(cls, twitch: Twitch, event: MessageEvent):
if event.chatter_user_login == "kurbezz":
return return
if ("kurbezz" in event.message.text.lower() or \ if ("kurbezz" in event.message.text.lower() or \
@@ -295,3 +302,31 @@ class MessagesProc:
"Пошел нахуй!", "Пошел нахуй!",
reply_parent_message_id=event.message_id reply_parent_message_id=event.message_id
) )
@classmethod
async def _on_custom_reward(cls, twitch: Twitch, event: MessageEvent):
pass
# if event.channel_points_custom_reward_id:
# await twitch.send_chat_message(
# event.broadcaster_user_id,
# config.TWITCH_ADMIN_USER_ID,
# "Спасибо за поддержку!",
# reply_parent_message_id=event.message_id
# )
@classmethod
async def on_message(cls, event: MessageEvent):
if event.chatter_user_name in cls.FULL_IGNORED_USER_LOGINS:
return
logging.info(f"Received message: {event}")
await cls._update_history(event)
twitch = await authorize()
await cls._goida(twitch, event)
await cls._lasqexx(twitch, event)
await cls._ask_ai(twitch, event)
await cls._kurbezz(twitch, event)
await cls._on_custom_reward(twitch, event)

View File

@@ -0,0 +1,39 @@
import logging
from pydantic import BaseModel
from twitchAPI.object.eventsub import ChannelPointsCustomRewardRedemptionAddEvent
from core.config import config
from .twitch.authorize import authorize
logger = logging.getLogger(__name__)
class RewardRedemption(BaseModel):
broadcaster_user_id: str
user_name: str
reward_title: str
reward_prompt: str
@classmethod
def from_twitch_event(cls, event: ChannelPointsCustomRewardRedemptionAddEvent):
return cls(
broadcaster_user_id=event.event.broadcaster_user_id,
user_name=event.event.user_name,
reward_title=event.event.reward.title,
reward_prompt=event.event.reward.prompt or "",
)
async def on_redemption_reward_add(reward: RewardRedemption):
logger.info(reward)
twitch = await authorize()
await twitch.send_chat_message(
reward.broadcaster_user_id,
config.TWITCH_ADMIN_USER_ID,
f"🎉 {reward.user_name} just redeemed {reward.reward_title}! 🎉"
)

View File

@@ -9,6 +9,7 @@ from .state import State, UpdateEvent, EventType
from .watcher import StateWatcher from .watcher import StateWatcher
from .messages_proc import MessageEvent, MessagesProc from .messages_proc import MessageEvent, MessagesProc
from .twitch.authorize import authorize from .twitch.authorize import authorize
from .reward_redemption import RewardRedemption, on_redemption_reward_add
@broker.task( @broker.task(
@@ -82,3 +83,11 @@ async def check_streams_states():
) )
async def on_message(event: MessageEvent): async def on_message(event: MessageEvent):
await MessagesProc.on_message(event) await MessagesProc.on_message(event)
@broker.task(
"stream_notifications.on_redemption_reward_add",
retry_on_error=True
)
async def on_redemption_reward_add_task(event: RewardRedemption):
await on_redemption_reward_add(event)

View File

@@ -14,6 +14,8 @@ SCOPES = [
AuthScope.USER_BOT, AuthScope.USER_BOT,
AuthScope.USER_READ_CHAT, AuthScope.USER_READ_CHAT,
AuthScope.USER_WRITE_CHAT, AuthScope.USER_WRITE_CHAT,
AuthScope.CHANNEL_READ_REDEMPTIONS,
] ]

View File

@@ -4,14 +4,15 @@ from typing import NoReturn, Literal
from twitchAPI.eventsub.webhook import EventSubWebhook from twitchAPI.eventsub.webhook import EventSubWebhook
from twitchAPI.twitch import Twitch from twitchAPI.twitch import Twitch
from twitchAPI.object.eventsub import StreamOnlineEvent, ChannelUpdateEvent, ChannelChatMessageEvent from twitchAPI.object.eventsub import StreamOnlineEvent, ChannelUpdateEvent, ChannelChatMessageEvent, ChannelPointsCustomRewardRedemptionAddEvent
from twitchAPI.oauth import validate_token from twitchAPI.oauth import validate_token
from core.config import config from core.config import config
from repositories.streamers import StreamerConfigRepository, StreamerConfig from repositories.streamers import StreamerConfigRepository, StreamerConfig
from modules.stream_notifications.tasks import on_stream_state_change, on_stream_state_change_with_check, on_message from modules.stream_notifications.tasks import on_stream_state_change, on_stream_state_change_with_check, on_message, on_redemption_reward_add_task
from modules.stream_notifications.state import UpdateEvent, EventType from modules.stream_notifications.state import UpdateEvent, EventType
from modules.stream_notifications.messages_proc import MessageEvent from modules.stream_notifications.messages_proc import MessageEvent
from modules.stream_notifications.reward_redemption import RewardRedemption
from .authorize import authorize from .authorize import authorize
@@ -42,6 +43,14 @@ class TwitchService:
EventType.STREAM_ONLINE, EventType.STREAM_ONLINE,
) )
async def on_channel_points_custom_reward_redemption_add(
self,
event: ChannelPointsCustomRewardRedemptionAddEvent
):
await on_redemption_reward_add_task(
RewardRedemption.from_twitch_event(event)
)
async def on_message(self, event: ChannelChatMessageEvent): async def on_message(self, event: ChannelChatMessageEvent):
await on_message.kiq( await on_message.kiq(
MessageEvent.from_twitch_event(event) MessageEvent.from_twitch_event(event)
@@ -51,7 +60,8 @@ class TwitchService:
self, self,
method: Literal["listen_channel_update_v2"] method: Literal["listen_channel_update_v2"]
| Literal["listen_stream_online"] | Literal["listen_stream_online"]
| Literal["listen_channel_chat_message"], | Literal["listen_channel_chat_message"]
| Literal["listen_channel_points_custom_reward_redemption_add"],
eventsub: EventSubWebhook, eventsub: EventSubWebhook,
streamer: StreamerConfig, streamer: StreamerConfig,
retry: int = 10 retry: int = 10
@@ -69,6 +79,11 @@ class TwitchService:
str(config.TWITCH_ADMIN_USER_ID), str(config.TWITCH_ADMIN_USER_ID),
self.on_message self.on_message
) )
case "listen_channel_points_custom_reward_redemption_add":
await eventsub.listen_channel_points_custom_reward_redemption_add(
str(streamer.twitch.id),
self.on_channel_points_custom_reward_redemption_add
)
case _: case _:
raise ValueError("Unknown method") raise ValueError("Unknown method")
@@ -84,6 +99,8 @@ class TwitchService:
sub_type = "stream.online" sub_type = "stream.online"
case "listen_channel_chat_message": case "listen_channel_chat_message":
sub_type = "channel.chat.message" sub_type = "channel.chat.message"
case "listen_channel_points_custom_reward_redemption_add":
sub_type = "channel.channel_points_custom_reward_redemption.add"
case _: case _:
raise ValueError("Unknown method") raise ValueError("Unknown method")
@@ -107,6 +124,7 @@ class TwitchService:
self.subscribe_with_retry("listen_channel_update_v2", eventsub, streamer), self.subscribe_with_retry("listen_channel_update_v2", eventsub, streamer),
self.subscribe_with_retry("listen_stream_online", eventsub, streamer), self.subscribe_with_retry("listen_stream_online", eventsub, streamer),
self.subscribe_with_retry("listen_channel_chat_message", eventsub, streamer), self.subscribe_with_retry("listen_channel_chat_message", eventsub, streamer),
self.subscribe_with_retry("listen_channel_points_custom_reward_redemption_add", eventsub, streamer)
) )
logger.info(f"Subscribe to events for {streamer.twitch.name} done") logger.info(f"Subscribe to events for {streamer.twitch.name} done")