diff --git a/app/services/notifications_youtube_video.py b/app/services/notifications_youtube_video.py index 73d1904..8a16ae2 100644 --- a/app/services/notifications_youtube_video.py +++ b/app/services/notifications_youtube_video.py @@ -1,3 +1,4 @@ +import random from typing import Any, Dict import discord @@ -7,6 +8,7 @@ from app.constants import LogTypes as logconstants from app.data.notifications_youtube_video import ( count_youtube_video_subscription_by_guilds, + find_guilds_by_youtuber, ) from app.services import cache from app.services.moderations import ( @@ -25,6 +27,80 @@ async def manager(interaction: discord.Interaction, guild_id: str): interaction, constants.NOTIFICATIONS_YOUTUBE_VIDEO_KEY, cogs ) +def send_youtube_video_notification(video_id: str, channel_id: str) -> None: + youtuber_info = bot.youtube.get_channel_info(channel_id) + video_info = bot.youtube.get_video_info(video_id) + youtuber_user = youtuber_info.get("customUrl").replace("@", "") + + guilds_data = find_guilds_by_youtuber(youtuber_user) + + logger.info( + f"Starting to send notifications for youtube video: **{youtuber_user}**", + log_type=logconstants.COMMAND_INFO_TYPE, + ) + + count = 0 + for guild_data in guilds_data: + guild = bot.get_guild(int(guild_data.get("guild_id"))) + + notifications = guild_data.get("notifications").get("values") + for notification in notifications: + youtuber = notification.get("youtuber").get("value") + if youtuber != youtuber_user: + continue + + message = compose_notification_message(notification, youtuber, video_id) + channel = guild.get_channel(int(notification.get("channel").get("value"))) + + embed = create_video_notification_embed(video_info, youtuber_info) + + bot.loop.create_task(channel.send(content=message, embed=embed)) + count += 1 + + logger.info( + f"Notifications sent for youtuber **{youtuber_user}** new video in {count} guilds", + log_type=logconstants.COMMAND_INFO_TYPE, + ) + +def create_video_notification_embed(video_info: Dict[str, Any], youtuber_info: Dict[str, Any]) -> discord.Embed: + video_link = f"https://www.youtube.com/watch?v={video_info.get('id')}" + video_thumbnail = video_info.get("thumbnails").get("maxres") or video_info.get("thumbnails").get("high") + + description = youtuber_info.get("description") + profile_picture = youtuber_info.get("thumbnails").get("high").get("url") + + embed = discord.Embed( + title=video_info.get("title"), + description=description.split("\n")[0], + url=video_link, + color=discord.Color.red(), + ) + + video_description = video_info.get("description").split("\n")[0] + video_tags = ", ".join(video_info.get("tags")[:3]) + + embed.set_thumbnail(url=profile_picture) + embed.set_image(url=video_thumbnail.get("url")) + embed.add_field(name="Description", value=video_description, inline=True) + embed.add_field(name="Tags", value=video_tags, inline=True) + + return embed + +def compose_notification_message(notification: Dict[str, Any], youtuber: str, video_id: str) -> str: + messages = notification.get("notification_messages").get("value") + video_link = f"https://www.youtube.com/watch?v={video_id}" + random_message = random.choice(messages.split(";")).lstrip() + + return parse_streamer_message(random_message, youtuber, video_link) + +def parse_streamer_message(message: str, youtuber: str, video_link: str) -> str: + if "{video_link}" not in message.lower(): + message += "\n{video_link}" + + message = message.format(youtuber=youtuber, video_link=video_link) + + return message + def subscribe_youtube_new_video(interaction: discord.Interaction, form_responses: Dict[str, Any]): for response in form_responses[0].get("value"): youtuber = response.get("youtuber").get("value") diff --git a/app/webhooks/youtube.py b/app/webhooks/youtube.py index 5984c9a..837fdc8 100644 --- a/app/webhooks/youtube.py +++ b/app/webhooks/youtube.py @@ -1,19 +1,36 @@ +import re + from flask import request from app import logger from app.constants import LogTypes as logconstants from app.webhooks import webhooks +pattern_video_id = r'(.*?)' +pattern_channel_id = r'(.*?)' @webhooks.route('/youtube', methods=['GET', 'POST']) def youtube_webhook(): - # from app import bot - challenge = request.args.get('hub.challenge') - if (challenge): + if challenge: return challenge - logger.info(f'Received Youtube webhook: {request.data}', log_type=logconstants.COMMAND_INFO_TYPE) + data = request.data.decode('utf-8') + + logger.info(f'Received Youtube webhook: {data}', log_type=logconstants.COMMAND_INFO_TYPE) + + match_video_id = re.search(pattern_video_id, data) + match_channel_id = re.search(pattern_channel_id, data) + + if not match_video_id or not match_channel_id: + logger.error('Invalid Youtube webhook data', log_type=logconstants.COMMAND_INFO_TYPE) + return 'Invalid request data', 403 + + from app.services.notifications_youtube_video import send_youtube_video_notification + + logger.info(f'Video ID: {match_video_id}, Channel ID: {match_channel_id}') + + send_youtube_video_notification(match_video_id, match_channel_id) - return 'Processed', 204 + return 'Webhook processed', 204