dragonxd1 commited on
Commit
5dbc4c8
·
verified ·
1 Parent(s): b6e4391

Update DragMusic/platforms/Youtube.py

Browse files
Files changed (1) hide show
  1. DragMusic/platforms/Youtube.py +87 -191
DragMusic/platforms/Youtube.py CHANGED
@@ -1,36 +1,15 @@
1
-
2
- # All rights reserved.
3
- #
4
  import asyncio
5
  import os
6
- import random
7
  import re
 
8
 
9
- from async_lru import alru_cache
10
- from py_yt import VideosSearch
11
  from pyrogram.enums import MessageEntityType
12
  from pyrogram.types import Message
13
- from yt_dlp import YoutubeDL
14
-
15
- import config
16
- from VenomX.utils.database import is_on_off
17
- from VenomX.utils.decorators import asyncify
18
- from VenomX.utils.formatters import seconds_to_min, time_to_seconds
19
-
20
- NOTHING = {"cookies_dead": None}
21
 
22
-
23
- def cookies():
24
- folder_path = f"{os.getcwd()}/cookies"
25
- txt_files = [file for file in os.listdir(folder_path) if file.endswith(".txt")]
26
- if not txt_files:
27
- raise FileNotFoundError(
28
- "No Cookies found in cookies directory make sure your cookies file written .txt file"
29
- )
30
- cookie_txt_file = random.choice(txt_files)
31
- cookie_txt_file = os.path.join(folder_path, cookie_txt_file)
32
- return cookie_txt_file
33
- # return f"""cookies/{str(cookie_txt_file).split("/")[-1]}"""
34
 
35
 
36
  async def shell_cmd(cmd):
@@ -48,7 +27,7 @@ async def shell_cmd(cmd):
48
  return out.decode("utf-8")
49
 
50
 
51
- class YouTube:
52
  def __init__(self):
53
  self.base = "https://www.youtube.com/watch?v="
54
  self.regex = r"(?:youtube\.com|youtu\.be)"
@@ -56,7 +35,7 @@ class YouTube:
56
  self.listbase = "https://youtube.com/playlist?list="
57
  self.reg = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
58
 
59
- async def exists(self, link: str, videoid: bool | str = None):
60
  if videoid:
61
  link = self.base + link
62
  if re.search(self.regex, link):
@@ -64,17 +43,7 @@ class YouTube:
64
  else:
65
  return False
66
 
67
- @property
68
- def use_fallback(self):
69
- return NOTHING["cookies_dead"] is True
70
-
71
- @use_fallback.setter
72
- def use_fallback(self, value):
73
- if NOTHING["cookies_dead"] is None:
74
- NOTHING["cookies_dead"] = value
75
-
76
- @asyncify
77
- def url(self, message_1: Message) -> str | None:
78
  messages = [message_1]
79
  if message_1.reply_to_message:
80
  messages.append(message_1.reply_to_message)
@@ -98,8 +67,7 @@ class YouTube:
98
  return None
99
  return text[offset : offset + length]
100
 
101
- @alru_cache(maxsize=None)
102
- async def details(self, link: str, videoid: bool | str = None):
103
  if videoid:
104
  link = self.base + link
105
  if "&" in link:
@@ -116,8 +84,7 @@ class YouTube:
116
  duration_sec = int(time_to_seconds(duration_min))
117
  return title, duration_min, duration_sec, thumbnail, vidid
118
 
119
- @alru_cache(maxsize=None)
120
- async def title(self, link: str, videoid: bool | str = None):
121
  if videoid:
122
  link = self.base + link
123
  if "&" in link:
@@ -127,8 +94,7 @@ class YouTube:
127
  title = result["title"]
128
  return title
129
 
130
- @alru_cache(maxsize=None)
131
- async def duration(self, link: str, videoid: bool | str = None):
132
  if videoid:
133
  link = self.base + link
134
  if "&" in link:
@@ -138,8 +104,7 @@ class YouTube:
138
  duration = result["duration"]
139
  return duration
140
 
141
- @alru_cache(maxsize=None)
142
- async def thumbnail(self, link: str, videoid: bool | str = None):
143
  if videoid:
144
  link = self.base + link
145
  if "&" in link:
@@ -149,22 +114,19 @@ class YouTube:
149
  thumbnail = result["thumbnails"][0]["url"].split("?")[0]
150
  return thumbnail
151
 
152
- async def video(self, link: str, videoid: bool | str = None):
153
  if videoid:
154
  link = self.base + link
155
  if "&" in link:
156
  link = link.split("&")[0]
157
- cmd = [
158
  "yt-dlp",
159
- f"--cookies",
160
- cookies(),
161
  "-g",
162
  "-f",
163
  "best[height<=?720][width<=?1280]",
164
  f"{link}",
165
- ]
166
- proc = await asyncio.create_subprocess_exec(
167
- *cmd,
168
  stdout=asyncio.subprocess.PIPE,
169
  stderr=asyncio.subprocess.PIPE,
170
  )
@@ -174,109 +136,67 @@ class YouTube:
174
  else:
175
  return 0, stderr.decode()
176
 
177
- @alru_cache(maxsize=None)
178
- async def playlist(self, link, limit, videoid: bool | str = None):
179
  if videoid:
180
  link = self.listbase + link
181
  if "&" in link:
182
  link = link.split("&")[0]
183
-
184
- cmd = (
185
- f"yt-dlp -i --compat-options no-youtube-unavailable-videos "
186
- f'--get-id --flat-playlist --playlist-end {limit} --skip-download "{link}" '
187
- f"2>/dev/null"
188
  )
189
-
190
- playlist = await shell_cmd(cmd)
191
-
192
  try:
193
- result = [key for key in playlist.split("\n") if key]
194
- except Exception:
 
 
 
195
  result = []
196
  return result
197
 
198
- @alru_cache(maxsize=None)
199
- async def track(self, link: str, videoid: bool | str = None):
200
  if videoid:
201
  link = self.base + link
202
  if "&" in link:
203
  link = link.split("&")[0]
204
- if link.startswith("http://") or link.startswith("https://"):
205
- return await self._track(link)
206
- try:
207
- results = VideosSearch(link, limit=1)
208
- for result in (await results.next())["result"]:
209
- title = result["title"]
210
- duration_min = result["duration"]
211
- vidid = result["id"]
212
- yturl = result["link"]
213
- thumbnail = result["thumbnails"][0]["url"].split("?")[0]
214
- track_details = {
215
- "title": title,
216
- "link": yturl,
217
- "vidid": vidid,
218
- "duration_min": duration_min,
219
- "thumb": thumbnail,
220
- }
221
- return track_details, vidid
222
- except Exception:
223
- return await self._track(link)
224
-
225
- @asyncify
226
- def _track(self, q):
227
- options = {
228
- "format": "best",
229
- "noplaylist": True,
230
- "quiet": True,
231
- "extract_flat": "in_playlist",
232
- "cookiefile": f"{cookies()}",
233
  }
234
- with YoutubeDL(options) as ydl:
235
- info_dict = ydl.extract_info(f"ytsearch: {q}", download=False)
236
- details = info_dict.get("entries")[0]
237
- info = {
238
- "title": details["title"],
239
- "link": details["url"],
240
- "vidid": details["id"],
241
- "duration_min": (
242
- seconds_to_min(details["duration"])
243
- if details["duration"] != 0
244
- else None
245
- ),
246
- "thumb": details["thumbnails"][0]["url"],
247
- }
248
- return info, details["id"]
249
 
250
- @alru_cache(maxsize=None)
251
- @asyncify
252
- def formats(self, link: str, videoid: bool | str = None):
253
  if videoid:
254
  link = self.base + link
255
  if "&" in link:
256
  link = link.split("&")[0]
257
-
258
- ytdl_opts = {
259
- "quiet": True,
260
- "cookiefile": f"{cookies()}",
261
- }
262
-
263
- ydl = YoutubeDL(ytdl_opts)
264
  with ydl:
265
  formats_available = []
266
  r = ydl.extract_info(link, download=False)
267
  for format in r["formats"]:
268
  try:
269
  str(format["format"])
270
- except Exception:
271
  continue
272
- if "dash" not in str(format["format"]).lower():
273
  try:
274
  format["format"]
275
  format["filesize"]
276
  format["format_id"]
277
  format["ext"]
278
  format["format_note"]
279
- except KeyError:
280
  continue
281
  formats_available.append(
282
  {
@@ -290,12 +210,11 @@ class YouTube:
290
  )
291
  return formats_available, link
292
 
293
- @alru_cache(maxsize=None)
294
  async def slider(
295
  self,
296
  link: str,
297
  query_type: int,
298
- videoid: bool | str = None,
299
  ):
300
  if videoid:
301
  link = self.base + link
@@ -313,90 +232,76 @@ class YouTube:
313
  self,
314
  link: str,
315
  mystic,
316
- video: bool | str = None,
317
- videoid: bool | str = None,
318
- songaudio: bool | str = None,
319
- songvideo: bool | str = None,
320
- format_id: bool | str = None,
321
- title: bool | str = None,
322
  ) -> str:
323
  if videoid:
324
  link = self.base + link
 
325
 
326
- @asyncify
327
  def audio_dl():
328
  ydl_optssx = {
 
329
  "format": "bestaudio/best",
330
  "outtmpl": "downloads/%(id)s.%(ext)s",
331
  "geo_bypass": True,
332
- "noplaylist": True,
333
  "nocheckcertificate": True,
334
  "quiet": True,
335
  "no_warnings": True,
336
- "cookiefile": f"{cookies()}",
337
- "prefer_ffmpeg": True,
338
  }
339
-
340
- with YoutubeDL(ydl_optssx) as x:
341
- info = x.extract_info(link, False)
342
- xyz = os.path.join("downloads", f"{info['id']}.{info['ext']}")
343
- if os.path.exists(xyz):
344
- return xyz
345
- x.download([link])
346
  return xyz
 
 
347
 
348
- @asyncify
349
  def video_dl():
350
  ydl_optssx = {
351
  "format": "(bestvideo[height<=?720][width<=?1280][ext=mp4])+(bestaudio[ext=m4a])",
352
  "outtmpl": "downloads/%(id)s.%(ext)s",
353
  "geo_bypass": True,
354
- "noplaylist": True,
355
  "nocheckcertificate": True,
356
  "quiet": True,
357
  "no_warnings": True,
358
- "prefer_ffmpeg": True,
359
- "cookiefile": f"{cookies()}",
360
  }
361
-
362
- with YoutubeDL(ydl_optssx) as x:
363
- info = x.extract_info(link, False)
364
- xyz = os.path.join("downloads", f"{info['id']}.{info['ext']}")
365
- if os.path.exists(xyz):
366
- return xyz
367
- x.download([link])
368
  return xyz
 
 
369
 
370
- @asyncify
371
  def song_video_dl():
372
  formats = f"{format_id}+140"
373
  fpath = f"downloads/{title}"
374
  ydl_optssx = {
 
375
  "format": formats,
376
  "outtmpl": fpath,
377
  "geo_bypass": True,
378
- "noplaylist": True,
379
  "nocheckcertificate": True,
380
  "quiet": True,
381
  "no_warnings": True,
382
  "prefer_ffmpeg": True,
383
  "merge_output_format": "mp4",
384
- "cookiefile": f"{cookies()}",
385
  }
 
 
386
 
387
- with YoutubeDL(ydl_optssx) as x:
388
- info = x.extract_info(link)
389
- file_path = x.prepare_filename(info)
390
- return file_path
391
-
392
- @asyncify
393
  def song_audio_dl():
394
  fpath = f"downloads/{title}.%(ext)s"
395
  ydl_optssx = {
 
396
  "format": format_id,
397
  "outtmpl": fpath,
398
  "geo_bypass": True,
399
- "noplaylist": True,
400
  "nocheckcertificate": True,
401
  "quiet": True,
402
  "no_warnings": True,
@@ -408,50 +313,41 @@ class YouTube:
408
  "preferredquality": "192",
409
  }
410
  ],
411
- "cookiefile": f"{cookies()}",
412
  }
413
-
414
- with YoutubeDL(ydl_optssx) as x:
415
- info = x.extract_info(link)
416
- file_path = x.prepare_filename(info)
417
- return file_path
418
 
419
  if songvideo:
420
- return await song_video_dl()
421
-
 
422
  elif songaudio:
423
- return await song_audio_dl()
424
-
 
425
  elif video:
426
- if await is_on_off(config.YTDOWNLOADER):
427
  direct = True
428
- downloaded_file = await video_dl()
429
  else:
430
- command = [
431
  "yt-dlp",
432
- f"--cookies",
433
- cookies(),
434
  "-g",
435
  "-f",
436
- "best",
437
- link,
438
- ]
439
-
440
- proc = await asyncio.create_subprocess_exec(
441
- *command,
442
  stdout=asyncio.subprocess.PIPE,
443
  stderr=asyncio.subprocess.PIPE,
444
  )
445
  stdout, stderr = await proc.communicate()
446
-
447
  if stdout:
448
  downloaded_file = stdout.decode().split("\n")[0]
449
  direct = None
450
  else:
451
- downloaded_file = await video_dl()
452
- direct = True
453
  else:
454
  direct = True
455
- downloaded_file = await audio_dl()
456
-
457
  return downloaded_file, direct
 
 
 
 
1
  import asyncio
2
  import os
 
3
  import re
4
+ from typing import Union
5
 
6
+ import yt_dlp
 
7
  from pyrogram.enums import MessageEntityType
8
  from pyrogram.types import Message
9
+ from youtubesearchpython.__future__ import VideosSearch
 
 
 
 
 
 
 
10
 
11
+ from DragMusic.utils.database import is_on_off
12
+ from DragMusic.utils.formatters import time_to_seconds
 
 
 
 
 
 
 
 
 
 
13
 
14
 
15
  async def shell_cmd(cmd):
 
27
  return out.decode("utf-8")
28
 
29
 
30
+ class YouTubeAPI:
31
  def __init__(self):
32
  self.base = "https://www.youtube.com/watch?v="
33
  self.regex = r"(?:youtube\.com|youtu\.be)"
 
35
  self.listbase = "https://youtube.com/playlist?list="
36
  self.reg = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
37
 
38
+ async def exists(self, link: str, videoid: Union[bool, str] = None):
39
  if videoid:
40
  link = self.base + link
41
  if re.search(self.regex, link):
 
43
  else:
44
  return False
45
 
46
+ async def url(self, message_1: Message) -> Union[str, None]:
 
 
 
 
 
 
 
 
 
 
47
  messages = [message_1]
48
  if message_1.reply_to_message:
49
  messages.append(message_1.reply_to_message)
 
67
  return None
68
  return text[offset : offset + length]
69
 
70
+ async def details(self, link: str, videoid: Union[bool, str] = None):
 
71
  if videoid:
72
  link = self.base + link
73
  if "&" in link:
 
84
  duration_sec = int(time_to_seconds(duration_min))
85
  return title, duration_min, duration_sec, thumbnail, vidid
86
 
87
+ async def title(self, link: str, videoid: Union[bool, str] = None):
 
88
  if videoid:
89
  link = self.base + link
90
  if "&" in link:
 
94
  title = result["title"]
95
  return title
96
 
97
+ async def duration(self, link: str, videoid: Union[bool, str] = None):
 
98
  if videoid:
99
  link = self.base + link
100
  if "&" in link:
 
104
  duration = result["duration"]
105
  return duration
106
 
107
+ async def thumbnail(self, link: str, videoid: Union[bool, str] = None):
 
108
  if videoid:
109
  link = self.base + link
110
  if "&" in link:
 
114
  thumbnail = result["thumbnails"][0]["url"].split("?")[0]
115
  return thumbnail
116
 
117
+ async def video(self, link: str, videoid: Union[bool, str] = None):
118
  if videoid:
119
  link = self.base + link
120
  if "&" in link:
121
  link = link.split("&")[0]
122
+ proc = await asyncio.create_subprocess_exec(
123
  "yt-dlp",
124
+ "--cookies",
125
+ "cookies.txt",
126
  "-g",
127
  "-f",
128
  "best[height<=?720][width<=?1280]",
129
  f"{link}",
 
 
 
130
  stdout=asyncio.subprocess.PIPE,
131
  stderr=asyncio.subprocess.PIPE,
132
  )
 
136
  else:
137
  return 0, stderr.decode()
138
 
139
+ async def playlist(self, link, limit, user_id, videoid: Union[bool, str] = None):
 
140
  if videoid:
141
  link = self.listbase + link
142
  if "&" in link:
143
  link = link.split("&")[0]
144
+ playlist = await shell_cmd(
145
+ f"yt-dlp --cookies cookies.txt -i --get-id --flat-playlist --playlist-end {limit} --skip-download {link}"
 
 
 
146
  )
 
 
 
147
  try:
148
+ result = playlist.split("\n")
149
+ for key in result:
150
+ if key == "":
151
+ result.remove(key)
152
+ except:
153
  result = []
154
  return result
155
 
156
+ async def track(self, link: str, videoid: Union[bool, str] = None):
 
157
  if videoid:
158
  link = self.base + link
159
  if "&" in link:
160
  link = link.split("&")[0]
161
+ results = VideosSearch(link, limit=1)
162
+ for result in (await results.next())["result"]:
163
+ title = result["title"]
164
+ duration_min = result["duration"]
165
+ vidid = result["id"]
166
+ yturl = result["link"]
167
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
168
+ track_details = {
169
+ "title": title,
170
+ "link": yturl,
171
+ "vidid": vidid,
172
+ "duration_min": duration_min,
173
+ "thumb": thumbnail,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  }
175
+ return track_details, vidid
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
 
177
+ async def formats(self, link: str, videoid: Union[bool, str] = None):
 
 
178
  if videoid:
179
  link = self.base + link
180
  if "&" in link:
181
  link = link.split("&")[0]
182
+ ytdl_opts = {"cookiefile": "cookies.txt", "quiet": True}
183
+ ydl = yt_dlp.YoutubeDL(ytdl_opts)
 
 
 
 
 
184
  with ydl:
185
  formats_available = []
186
  r = ydl.extract_info(link, download=False)
187
  for format in r["formats"]:
188
  try:
189
  str(format["format"])
190
+ except:
191
  continue
192
+ if not "dash" in str(format["format"]).lower():
193
  try:
194
  format["format"]
195
  format["filesize"]
196
  format["format_id"]
197
  format["ext"]
198
  format["format_note"]
199
+ except:
200
  continue
201
  formats_available.append(
202
  {
 
210
  )
211
  return formats_available, link
212
 
 
213
  async def slider(
214
  self,
215
  link: str,
216
  query_type: int,
217
+ videoid: Union[bool, str] = None,
218
  ):
219
  if videoid:
220
  link = self.base + link
 
232
  self,
233
  link: str,
234
  mystic,
235
+ video: Union[bool, str] = None,
236
+ videoid: Union[bool, str] = None,
237
+ songaudio: Union[bool, str] = None,
238
+ songvideo: Union[bool, str] = None,
239
+ format_id: Union[bool, str] = None,
240
+ title: Union[bool, str] = None,
241
  ) -> str:
242
  if videoid:
243
  link = self.base + link
244
+ loop = asyncio.get_running_loop()
245
 
 
246
  def audio_dl():
247
  ydl_optssx = {
248
+ "cookiefile": "cookies.txt",
249
  "format": "bestaudio/best",
250
  "outtmpl": "downloads/%(id)s.%(ext)s",
251
  "geo_bypass": True,
 
252
  "nocheckcertificate": True,
253
  "quiet": True,
254
  "no_warnings": True,
 
 
255
  }
256
+ x = yt_dlp.YoutubeDL(ydl_optssx)
257
+ info = x.extract_info(link, False)
258
+ xyz = os.path.join("downloads", f"{info['id']}.{info['ext']}")
259
+ if os.path.exists(xyz):
 
 
 
260
  return xyz
261
+ x.download([link])
262
+ return xyz
263
 
 
264
  def video_dl():
265
  ydl_optssx = {
266
  "format": "(bestvideo[height<=?720][width<=?1280][ext=mp4])+(bestaudio[ext=m4a])",
267
  "outtmpl": "downloads/%(id)s.%(ext)s",
268
  "geo_bypass": True,
 
269
  "nocheckcertificate": True,
270
  "quiet": True,
271
  "no_warnings": True,
 
 
272
  }
273
+ x = yt_dlp.YoutubeDL(ydl_optssx)
274
+ info = x.extract_info(link, False)
275
+ xyz = os.path.join("downloads", f"{info['id']}.{info['ext']}")
276
+ if os.path.exists(xyz):
 
 
 
277
  return xyz
278
+ x.download([link])
279
+ return xyz
280
 
 
281
  def song_video_dl():
282
  formats = f"{format_id}+140"
283
  fpath = f"downloads/{title}"
284
  ydl_optssx = {
285
+ "cookiefile": "cookies.txt",
286
  "format": formats,
287
  "outtmpl": fpath,
288
  "geo_bypass": True,
 
289
  "nocheckcertificate": True,
290
  "quiet": True,
291
  "no_warnings": True,
292
  "prefer_ffmpeg": True,
293
  "merge_output_format": "mp4",
 
294
  }
295
+ x = yt_dlp.YoutubeDL(ydl_optssx)
296
+ x.download([link])
297
 
 
 
 
 
 
 
298
  def song_audio_dl():
299
  fpath = f"downloads/{title}.%(ext)s"
300
  ydl_optssx = {
301
+ "cookiefile": "cookies.txt",
302
  "format": format_id,
303
  "outtmpl": fpath,
304
  "geo_bypass": True,
 
305
  "nocheckcertificate": True,
306
  "quiet": True,
307
  "no_warnings": True,
 
313
  "preferredquality": "192",
314
  }
315
  ],
 
316
  }
317
+ x = yt_dlp.YoutubeDL(ydl_optssx)
318
+ x.download([link])
 
 
 
319
 
320
  if songvideo:
321
+ await loop.run_in_executor(None, song_video_dl)
322
+ fpath = f"downloads/{title}.mp4"
323
+ return fpath
324
  elif songaudio:
325
+ await loop.run_in_executor(None, song_audio_dl)
326
+ fpath = f"downloads/{title}.mp3"
327
+ return fpath
328
  elif video:
329
+ if await is_on_off(1):
330
  direct = True
331
+ downloaded_file = await loop.run_in_executor(None, video_dl)
332
  else:
333
+ proc = await asyncio.create_subprocess_exec(
334
  "yt-dlp",
335
+ "--cookies",
336
+ "cookies.txt",
337
  "-g",
338
  "-f",
339
+ "best[height<=?720][width<=?1280]",
340
+ f"{link}",
 
 
 
 
341
  stdout=asyncio.subprocess.PIPE,
342
  stderr=asyncio.subprocess.PIPE,
343
  )
344
  stdout, stderr = await proc.communicate()
 
345
  if stdout:
346
  downloaded_file = stdout.decode().split("\n")[0]
347
  direct = None
348
  else:
349
+ return
 
350
  else:
351
  direct = True
352
+ downloaded_file = await loop.run_in_executor(None, audio_dl)
 
353
  return downloaded_file, direct