FunguyBot/plugins/youtube-preview.py

125 lines
4.2 KiB
Python
Raw Normal View History

"""
2024-03-03 23:34:39 +00:00
Plugin for providing a command to fetch YouTube video information from links.
"""
2024-03-03 23:34:39 +00:00
# Importing necessary libraries
import re
import logging
2024-03-03 23:34:39 +00:00
import asyncio
import aiohttp
2024-03-01 16:20:44 +00:00
from pytubefix import YouTube
import simplematrixbotlib as botlib
from youtube_title_parse import get_artist_title
LYRICIST_API_URL = "https://lyrist.vercel.app/api/{}"
def seconds_to_minutes_seconds(seconds):
2024-03-03 23:34:39 +00:00
"""
Converts seconds to a string representation of minutes and seconds.
Args:
seconds (int): The number of seconds.
Returns:
str: A string representation of minutes and seconds in the format MM:SS.
"""
minutes = seconds // 60
seconds %= 60
return f"{minutes:02d}:{seconds:02d}"
async def fetch_lyrics(song, artist):
"""
Asynchronously fetches lyrics for a song from the Lyricist API.
Args:
song (str): The name of the song.
artist (str): The name of the artist.
Returns:
str: Lyrics of the song.
None if an error occurs during fetching.
"""
try:
async with aiohttp.ClientSession() as session:
async with session.get(LYRICIST_API_URL.format(song, artist)) as response:
data = await response.json()
return data.get("lyrics")
except Exception as e:
logging.error(f"Error fetching lyrics: {str(e)}")
return None
2024-03-01 16:20:44 +00:00
async def fetch_youtube_info(youtube_url):
2024-03-03 23:34:39 +00:00
"""
Asynchronously fetches information about a YouTube video.
Args:
youtube_url (str): The URL of the YouTube video.
Returns:
str: A message containing information about the YouTube video.
None if an error occurs during fetching.
"""
2024-03-01 16:20:44 +00:00
try:
video = YouTube(youtube_url)
title = video.title
artist, song = get_artist_title(title)
2024-03-01 16:20:44 +00:00
description = video.description
length = seconds_to_minutes_seconds(video.length)
views = video.views
author = video.author
description_with_breaks = description.replace('\n', '<br>')
# Fetching lyrics
lyrics = await fetch_lyrics(song, artist)
lyrics = lyrics.replace('\n', "<br>")
info_message = f"""<strong>🎬🎝 Title:</strong> {title} | <strong>Length</strong>: {length} minutes | <strong>Views</strong>: {views}\n<details><summary><strong>⤵Description⤵</strong></summary>{description_with_breaks}</details>"""
if lyrics:
info_message += f"<br><details><summary><strong>🎵 Lyrics:</strong></summary><br>{lyrics}</details>"
2024-03-01 16:20:44 +00:00
return info_message
except Exception as e:
logging.error(f"Error fetching YouTube video information: {str(e)}")
return None
2024-03-01 16:20:44 +00:00
async def handle_command(room, message, bot, prefix, config):
2024-03-03 23:34:39 +00:00
"""
Asynchronously handles the command to fetch YouTube video information.
Args:
room (Room): The Matrix room where the command was invoked.
message (RoomMessage): The message object containing the command.
bot (MatrixBot): The Matrix bot instance.
prefix (str): The command prefix.
config (dict): The bot's configuration.
Returns:
None
"""
match = botlib.MessageMatch(room, message, bot, prefix)
2024-03-03 23:34:39 +00:00
if match.is_not_from_this_bot() and re.search(r'youtube\.com/watch\?v=', message.body):
logging.info("YouTube link detected")
video_id_match = re.search(r'youtube\.com/watch\?v=([^\s]+)', message.body)
if video_id_match:
video_id = video_id_match.group(1)
youtube_url = f"https://www.youtube.com/watch?v={video_id}"
logging.info(f"Fetching information for YouTube video: {youtube_url}")
2024-03-01 16:20:44 +00:00
retry_count = 3
while retry_count > 0:
info_message = await fetch_youtube_info(youtube_url)
if info_message:
await bot.api.send_markdown_message(room.room_id, info_message)
logging.info("Sent YouTube video information to the room")
break
else:
logging.info("Retrying...")
retry_count -= 1
await asyncio.sleep(1) # wait for 1 second before retrying
else:
logging.error("Failed to fetch YouTube video information after retries")