Coverage for mindsdb / integrations / handlers / youtube_handler / youtube_handler.py: 0%
61 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-21 00:36 +0000
1from mindsdb.integrations.handlers.youtube_handler.youtube_tables import (
2 YoutubeCommentsTable,
3 YoutubeChannelsTable,
4 YoutubeVideosTable,
5)
6from mindsdb.integrations.libs.api_handler import APIHandler
7from mindsdb.integrations.libs.response import (
8 HandlerStatusResponse as StatusResponse,
9)
10from mindsdb.utilities import log
11from mindsdb_sql_parser import parse_sql
13from mindsdb.utilities.config import Config
15from googleapiclient.discovery import build
17from mindsdb.integrations.utilities.handlers.auth_utilities.google import GoogleUserOAuth2Manager
19DEFAULT_SCOPES = [
20 'https://www.googleapis.com/auth/youtube',
21 'https://www.googleapis.com/auth/youtube.force-ssl',
22 'https://www.googleapis.com/auth/youtubepartner'
23]
25logger = log.getLogger(__name__)
28class YoutubeHandler(APIHandler):
29 """Youtube handler implementation"""
31 def __init__(self, name=None, **kwargs):
32 """Initialize the Youtube handler.
33 Parameters
34 ----------
35 name : str
36 name of a handler instance
37 """
38 super().__init__(name)
39 self.connection_data = kwargs.get("connection_data", {})
40 self.kwargs = kwargs
42 self.parser = parse_sql
43 self.connection = None
44 self.is_connected = False
46 self.handler_storage = kwargs['handler_storage']
48 self.credentials_url = self.connection_data.get('credentials_url', None)
49 self.credentials_file = self.connection_data.get('credentials_file', None)
50 if self.connection_data.get('credentials'):
51 self.credentials_file = self.connection_data.pop('credentials')
52 if not self.credentials_file and not self.credentials_url:
53 # try to get from config
54 yt_config = Config().get('handlers', {}).get('youtube', {})
55 secret_file = yt_config.get('credentials_file')
56 secret_url = yt_config.get('credentials_url')
57 if secret_file:
58 self.credentials_file = secret_file
59 elif secret_url:
60 self.credentials_url = secret_url
62 self.youtube_api_token = self.connection_data.get('youtube_api_token', None)
64 self.scopes = self.connection_data.get('scopes', DEFAULT_SCOPES)
66 youtube_video_comments_data = YoutubeCommentsTable(self)
67 self._register_table("comments", youtube_video_comments_data)
69 youtube_channel_data = YoutubeChannelsTable(self)
70 self._register_table("channels", youtube_channel_data)
72 youtube_video_data = YoutubeVideosTable(self)
73 self._register_table("videos", youtube_video_data)
75 def connect(self) -> StatusResponse:
76 """Set up the connection required by the handler.
77 Returns
78 -------
79 StatusResponse
80 connection object
81 """
82 if self.is_connected is True:
83 return self.connection
85 google_oauth2_manager = GoogleUserOAuth2Manager(self.handler_storage, self.scopes, self.credentials_file, self.credentials_url, self.connection_data.get('code'))
86 creds = google_oauth2_manager.get_oauth2_credentials()
88 youtube = build(
89 "youtube", "v3", developerKey=self.youtube_api_token, credentials=creds
90 )
91 self.connection = youtube
93 return self.connection
95 def check_connection(self) -> StatusResponse:
96 """Check connection to the handler.
97 Returns
98 -------
99 StatusResponse
100 Status confirmation
101 """
102 response = StatusResponse(False)
104 try:
105 self.connect()
106 response.success = True
107 response.copy_storage = True
108 except Exception as e:
109 logger.error(f"Error connecting to Youtube API: {e}!")
110 response.error_message = e
112 self.is_connected = response.success
114 return response
116 def native_query(self, query: str) -> StatusResponse:
117 """Receive and process a raw query.
118 Parameters
119 ----------
120 query : str
121 query in a native format
122 Returns
123 -------
124 StatusResponse
125 Request status
126 """
127 ast = parse_sql(query)
128 return self.query(ast)