dragonxd1 commited on
Commit
eda8225
·
verified ·
1 Parent(s): ccbafd2

Update DragMusic/platforms/Youtube.py

Browse files
Files changed (1) hide show
  1. DragMusic/platforms/Youtube.py +114 -393
DragMusic/platforms/Youtube.py CHANGED
@@ -1,76 +1,26 @@
1
  import asyncio
2
- import glob
3
- import json
4
  import os
5
- import random
6
  import re
7
- from concurrent.futures import ThreadPoolExecutor
8
- from typing import Union
9
- import string
10
- import requests
11
  import yt_dlp
 
12
  from pyrogram.enums import MessageEntityType
13
  from pyrogram.types import Message
14
- from requests.adapters import HTTPAdapter
15
- from urllib3.util.retry import Retry
16
- from youtubesearchpython.__future__ import VideosSearch, CustomSearch
17
- import base64
18
- from DragMusic import LOGGER
19
  from DragMusic.utils.database import is_on_off
20
  from DragMusic.utils.formatters import time_to_seconds
21
- from config import YT_API_KEY, YTPROXY_URL as YTPROXY
22
-
23
- logger = LOGGER(__name__)
24
-
25
- def cookie_txt_file():
26
- try:
27
- folder_path = f"{os.getcwd()}/cookies"
28
- filename = f"{os.getcwd()}/cookies/logs.csv"
29
- txt_files = glob.glob(os.path.join(folder_path, '*.txt'))
30
- if not txt_files:
31
- raise FileNotFoundError("No .txt files found in the specified folder.")
32
- cookie_txt_file = random.choice(txt_files)
33
- with open(filename, 'a') as file:
34
- file.write(f'Choosen File : {cookie_txt_file}\n')
35
- return f"""cookies/{str(cookie_txt_file).split("/")[-1]}"""
36
- except:
37
- return None
38
-
39
 
40
- async def check_file_size(link):
41
- async def get_format_info(link):
42
- proc = await asyncio.create_subprocess_exec(
43
- "yt-dlp",
44
- "--cookies", cookie_txt_file(),
45
- "-J",
46
- link,
47
- stdout=asyncio.subprocess.PIPE,
48
- stderr=asyncio.subprocess.PIPE
49
- )
50
- stdout, stderr = await proc.communicate()
51
- if proc.returncode != 0:
52
- print(f'Error:\n{stderr.decode()}')
53
- return None
54
- return json.loads(stdout.decode())
55
 
56
- def parse_size(formats):
57
- total_size = 0
58
- for format in formats:
59
- if 'filesize' in format:
60
- total_size += format['filesize']
61
- return total_size
62
 
63
- info = await get_format_info(link)
64
- if info is None:
65
- return None
66
-
67
- formats = info.get('formats', [])
68
- if not formats:
69
- print("No formats found.")
70
- return None
71
-
72
- total_size = parse_size(formats)
73
- return total_size
74
 
75
  async def shell_cmd(cmd):
76
  proc = await asyncio.create_subprocess_shell(
@@ -87,6 +37,21 @@ async def shell_cmd(cmd):
87
  return out.decode("utf-8")
88
 
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  class YouTubeAPI:
91
  def __init__(self):
92
  self.base = "https://www.youtube.com/watch?v="
@@ -94,49 +59,6 @@ class YouTubeAPI:
94
  self.status = "https://www.youtube.com/oembed?url="
95
  self.listbase = "https://youtube.com/playlist?list="
96
  self.reg = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
97
- self.dl_stats = {
98
- "total_requests": 0,
99
- "okflix_downloads": 0,
100
- "cookie_downloads": 0,
101
- "existing_files": 0
102
- }
103
-
104
- async def _get_video_details(self, link: str, limit: int = 20) -> Union[dict, None]:
105
- """Helper function to get video details with duration limit and error handling"""
106
- try:
107
- results = VideosSearch(link, limit=limit)
108
- search_results = (await results.next()).get("result", [])
109
-
110
- for result in search_results:
111
- duration_str = result.get("duration", "0:00")
112
-
113
- # Convert duration to seconds
114
- try:
115
- parts = duration_str.split(":")
116
- duration_secs = 0
117
- if len(parts) == 3: # HH:MM:SS
118
- duration_secs = int(parts[0]) * 3600 + int(parts[1]) * 60 + int(parts[2])
119
- elif len(parts) == 2: # MM:SS
120
- duration_secs = int(parts[0]) * 60 + int(parts[1])
121
-
122
- # Skip videos longer than 1 hour
123
- if duration_secs > 3600:
124
- continue
125
-
126
- return result
127
-
128
- except (ValueError, IndexError):
129
- continue
130
-
131
- search = CustomSearch(query=link, searchPreferences="EgIYAw==" ,limit=1)
132
- for res in (await search.next()).get("result", []):
133
- return res
134
-
135
- return None
136
-
137
- except Exception as e:
138
- LOGGER(__name__).error(f"Error in _get_video_details: {str(e)}")
139
- return None
140
 
141
  async def exists(self, link: str, videoid: Union[bool, str] = None):
142
  if videoid:
@@ -175,26 +97,16 @@ class YouTubeAPI:
175
  link = self.base + link
176
  if "&" in link:
177
  link = link.split("&")[0]
178
- if "?si=" in link:
179
- link = link.split("?si=")[0]
180
- elif "&si=" in link:
181
- link = link.split("&si=")[0]
182
-
183
-
184
- result = await self._get_video_details(link)
185
- if not result:
186
- raise ValueError("No suitable video found (duration > 1 hour or video unavailable)")
187
-
188
- title = result["title"]
189
- duration_min = result["duration"]
190
- thumbnail = result["thumbnails"][0]["url"].split("?")[0]
191
- vidid = result["id"]
192
-
193
- if str(duration_min) == "None":
194
- duration_sec = 0
195
- else:
196
- duration_sec = int(time_to_seconds(duration_min))
197
-
198
  return title, duration_min, duration_sec, thumbnail, vidid
199
 
200
  async def title(self, link: str, videoid: Union[bool, str] = None):
@@ -202,83 +114,47 @@ class YouTubeAPI:
202
  link = self.base + link
203
  if "&" in link:
204
  link = link.split("&")[0]
205
- if "?si=" in link:
206
- link = link.split("?si=")[0]
207
- elif "&si=" in link:
208
- link = link.split("&si=")[0]
209
-
210
- result = await self._get_video_details(link)
211
- if not result:
212
- raise ValueError("No suitable video found (duration > 1 hour or video unavailable)")
213
- return result["title"]
214
 
215
  async def duration(self, link: str, videoid: Union[bool, str] = None):
216
  if videoid:
217
  link = self.base + link
218
  if "&" in link:
219
  link = link.split("&")[0]
220
- if "?si=" in link:
221
- link = link.split("?si=")[0]
222
- elif "&si=" in link:
223
- link = link.split("&si=")[0]
224
-
225
- result = await self._get_video_details(link)
226
- if not result:
227
- raise ValueError("No suitable video found (duration > 1 hour or video unavailable)")
228
- return result["duration"]
229
 
230
  async def thumbnail(self, link: str, videoid: Union[bool, str] = None):
231
  if videoid:
232
  link = self.base + link
233
  if "&" in link:
234
  link = link.split("&")[0]
235
- if "?si=" in link:
236
- link = link.split("?si=")[0]
237
- elif "&si=" in link:
238
- link = link.split("&si=")[0]
239
-
240
- result = await self._get_video_details(link)
241
- if not result:
242
- raise ValueError("No suitable video found (duration > 1 hour or video unavailable)")
243
- return result["thumbnails"][0]["url"].split("?")[0]
244
 
245
  async def video(self, link: str, videoid: Union[bool, str] = None):
246
  if videoid:
247
  link = self.base + link
248
  if "&" in link:
249
  link = link.split("&")[0]
250
- if "?si=" in link:
251
- link = link.split("?si=")[0]
252
- elif "&si=" in link:
253
- link = link.split("&si=")[0]
254
-
255
- proc = await asyncio.create_subprocess_exec(
256
- "yt-dlp",
257
- "--cookies",cookie_txt_file(),
258
- "-g",
259
- "-f",
260
- "best[height<=?720][width<=?1280]",
261
- f"{link}",
262
- stdout=asyncio.subprocess.PIPE,
263
- stderr=asyncio.subprocess.PIPE,
264
- )
265
- stdout, stderr = await proc.communicate()
266
- if stdout:
267
- return 1, stdout.decode().split("\n")[0]
268
- else:
269
- return 0, stderr.decode()
270
 
271
  async def playlist(self, link, limit, user_id, videoid: Union[bool, str] = None):
272
  if videoid:
273
  link = self.listbase + link
274
  if "&" in link:
275
  link = link.split("&")[0]
276
- if "?si=" in link:
277
- link = link.split("?si=")[0]
278
- elif "&si=" in link:
279
- link = link.split("&si=")[0]
280
  playlist = await shell_cmd(
281
- f"yt-dlp -i --get-id --flat-playlist --cookies {cookie_txt_file()} --playlist-end {limit} --skip-download {link}"
282
  )
283
  try:
284
  result = playlist.split("\n")
@@ -294,34 +170,28 @@ class YouTubeAPI:
294
  link = self.base + link
295
  if "&" in link:
296
  link = link.split("&")[0]
297
- if "?si=" in link:
298
- link = link.split("?si=")[0]
299
- elif "&si=" in link:
300
- link = link.split("&si=")[0]
301
-
302
- result = await self._get_video_details(link)
303
- if not result:
304
- raise ValueError("No suitable video found (duration > 1 hour or video unavailable)")
305
-
306
  track_details = {
307
- "title": result["title"],
308
- "link": result["link"],
309
- "vidid": result["id"],
310
- "duration_min": result["duration"],
311
- "thumb": result["thumbnails"][0]["url"].split("?")[0],
312
  }
313
- return track_details, result["id"]
314
 
315
  async def formats(self, link: str, videoid: Union[bool, str] = None):
316
  if videoid:
317
  link = self.base + link
318
  if "&" in link:
319
  link = link.split("&")[0]
320
- if "?si=" in link:
321
- link = link.split("?si=")[0]
322
- elif "&si=" in link:
323
- link = link.split("&si=")[0]
324
- ytdl_opts = {"quiet": True, "cookiefile" : cookie_txt_file()}
325
  ydl = yt_dlp.YoutubeDL(ytdl_opts)
326
  with ydl:
327
  formats_available = []
@@ -352,51 +222,23 @@ class YouTubeAPI:
352
  )
353
  return formats_available, link
354
 
355
- async def slider(self, link: str, query_type: int, videoid: Union[bool, str] = None):
 
 
 
 
 
356
  if videoid:
357
  link = self.base + link
358
  if "&" in link:
359
  link = link.split("&")[0]
360
- if "?si=" in link:
361
- link = link.split("?si=")[0]
362
- elif "&si=" in link:
363
- link = link.split("&si=")[0]
364
-
365
- try:
366
- results = []
367
- search = VideosSearch(link, limit=10)
368
- search_results = (await search.next()).get("result", [])
369
-
370
- # Filter videos longer than 1 hour
371
- for result in search_results:
372
- duration_str = result.get("duration", "0:00")
373
- try:
374
- parts = duration_str.split(":")
375
- duration_secs = 0
376
- if len(parts) == 3:
377
- duration_secs = int(parts[0]) * 3600 + int(parts[1]) * 60 + int(parts[2])
378
- elif len(parts) == 2:
379
- duration_secs = int(parts[0]) * 60 + int(parts[1])
380
-
381
- if duration_secs <= 3600:
382
- results.append(result)
383
- except (ValueError, IndexError):
384
- continue
385
-
386
- if not results or query_type >= len(results):
387
- raise ValueError("No suitable videos found within duration limit")
388
-
389
- selected = results[query_type]
390
- return (
391
- selected["title"],
392
- selected["duration"],
393
- selected["thumbnails"][0]["url"].split("?")[0],
394
- selected["id"]
395
- )
396
-
397
- except Exception as e:
398
- LOGGER(__name__).error(f"Error in slider: {str(e)}")
399
- raise ValueError("Failed to fetch video details")
400
 
401
  async def download(
402
  self,
@@ -410,161 +252,43 @@ class YouTubeAPI:
410
  title: Union[bool, str] = None,
411
  ) -> str:
412
  if videoid:
413
- vid_id = link
414
  link = self.base + link
415
  loop = asyncio.get_running_loop()
416
 
417
- def create_session():
418
- session = requests.Session()
419
- retries = Retry(total=3, backoff_factor=0.1)
420
- session.mount('http://', HTTPAdapter(max_retries=retries))
421
- session.mount('https://', HTTPAdapter(max_retries=retries))
422
- return session
423
-
424
- def get_ydl_opts(output_path):
425
- return {
426
- "outtmpl": output_path,
427
- "quiet": True,
428
- "xff": "IN",
429
  "nocheckcertificate": True,
430
- "compat-options": "allow-unsafe-ext",
431
- "concurrent-fragments": 99, # Increased from 10
432
- "retries": 3,
433
- # "http-chunk-size": 10485760, # 10MB chunks
434
- # "buffersize": 32768,
435
  }
436
- ## Method added by sparrow...
437
- # def audio_dl(vid_id):
438
- # try:
439
- # session = create_session()
440
- # random_prefix = ''.join(random.choices(string.ascii_letters + string.digits, k=12))
441
- # ruseragent = f"{random_prefix} Mozilla/5.9 ({random.randint(1000, 9999)})"
442
- # bsid = base64.b64encode(vid_id.encode()).decode() ## For next update
443
- # headers = {
444
- # "x-api-key": f"{YT_API_KEY}",
445
- # "User-Agent": ruseragent
446
- # }
447
- # res = session.get(f"{YTPROXY}/api/info?video_id={vid_id}", headers=headers, timeout=300)
448
- # response = res.json()
449
-
450
- # if res.status_code == 200 and response['status'] == 'success':
451
- # xyz = os.path.join("downloads", f"{vid_id}.m4a")
452
- # if os.path.exists(xyz):
453
- # return xyz
454
-
455
- # with session.get(response['download_url'], headers=headers, stream=True, timeout=300) as r:
456
- # r.raise_for_status()
457
- # total_size = int(r.headers.get('content-length', 0))
458
- # block_size = 1024 * 1024 # 1MB chunks
459
-
460
- # with open(xyz, 'wb') as f:
461
- # for chunk in r.iter_content(chunk_size=block_size):
462
- # if chunk: # filter out keep-alive chunks
463
- # f.write(chunk)
464
-
465
- # return xyz
466
- # else:
467
- # print(f"Proxy returned error status: {response}")
468
-
469
- # except requests.exceptions.RequestException as e:
470
- # print(f"Network error while downloading: {str(e)}")
471
- # except json.JSONDecodeError as e:
472
- # print(f"Invalid response from proxy: {str(e)}")
473
- # except Exception as e:
474
- # print(f"Error in downloading song: {str(e)}")
475
- # return None
476
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
477
 
478
- # New updated Method...
479
- def audio_dl(vid_id):
480
- try:
481
- if not YT_API_KEY:
482
- print("API KEY not set in config, Set API Key you got from @tgmusic_apibot")
483
- return None
484
- if not YTPROXY:
485
- print("API Endpoint not set in config\nPlease set a valid endpoint for YTPROXY_URL in config.")
486
- return None
487
- headers = {
488
- "x-api-key": f"{YT_API_KEY}",
489
- "User-Agent": "Mozilla/5"
490
- }
491
- xyz = os.path.join("downloads", f"{vid_id}.mp3")
492
- if os.path.exists(xyz):
493
- return xyz
494
- getAudio = requests.get(f"{YTPROXY}/audio/{vid_id}", headers=headers, timeout=60)
495
- try:
496
- songData = getAudio.json()
497
- except Exception as e:
498
- print(f"Invalid response from API: {str(e)}")
499
- return None
500
- status = songData.get('status')
501
- if status == 'success':
502
- songlink = songData['audio_url']
503
- audio_url = base64.b64decode(songlink).decode()
504
- ydl_opts = get_ydl_opts(xyz)
505
- with ThreadPoolExecutor(max_workers=4) as executor:
506
- future = executor.submit(lambda: yt_dlp.YoutubeDL(ydl_opts).download(audio_url))
507
- future.result()
508
- return xyz
509
- elif status == 'error':
510
- print(f"Error: {songData.get('message', 'Unknown error from API.')}")
511
- return None
512
- else:
513
- print("Could not fetch Backend \nPlease contact API provider.")
514
- return None
515
- except requests.exceptions.RequestException as e:
516
- print(f"Network error while downloading: {str(e)}")
517
- except json.JSONDecodeError as e:
518
- print(f"Invalid response from proxy: {str(e)}")
519
- except Exception as e:
520
- print(f"Error in downloading song: {str(e)}")
521
- return None
522
-
523
- def video_dl(vid_id):
524
- try:
525
- if not YT_API_KEY:
526
- print("API KEY not set in config, Set API Key you got from @tgmusic_apibot")
527
- return None
528
- if not YTPROXY:
529
- print("API Endpoint not set in config\nPlease set a valid endpoint for YTPROXY_URL in config.")
530
- return None
531
- headers = {
532
- "x-api-key": f"{YT_API_KEY}",
533
- "User-Agent": "Mozilla/5"
534
- }
535
- xyz = os.path.join("downloads", f"{vid_id}.mp4")
536
- if os.path.exists(xyz):
537
- return xyz
538
- getVideo = requests.get(f"{YTPROXY}/beta/{vid_id}", headers=headers, timeout=60)
539
- try:
540
- videoData = getVideo.json()
541
- except Exception as e:
542
- print(f"Invalid response from API: {str(e)}")
543
- return None
544
- status = videoData.get('status')
545
- if status == 'success':
546
- videolink = videoData['video_sd']
547
- video_url = base64.b64decode(videolink).decode()
548
- logger.debug(f"Got video url {video_url}")
549
- ydl_opts = get_ydl_opts(f"downloads/{vid_id}.mp4")
550
- with ThreadPoolExecutor(max_workers=4) as executor:
551
- future = executor.submit(lambda: yt_dlp.YoutubeDL(ydl_opts).download(video_url))
552
- future.result()
553
- return xyz
554
- elif status == 'error':
555
- print(f"Error: {videoData.get('message', 'Unknown error from API.')}")
556
- return None
557
- else:
558
- print("Could not fetch Backend \nPlease contact API provider.")
559
- return None
560
- except requests.exceptions.RequestException as e:
561
- print(f"Network error while downloading: {str(e)}")
562
- except json.JSONDecodeError as e:
563
- print(f"Invalid response from proxy: {str(e)}")
564
- except Exception as e:
565
- print(f"Error in downloading song: {str(e)}")
566
- return None
567
-
568
  def song_video_dl():
569
  formats = f"{format_id}+140"
570
  fpath = f"downloads/{title}"
@@ -575,7 +299,6 @@ class YouTubeAPI:
575
  "nocheckcertificate": True,
576
  "quiet": True,
577
  "no_warnings": True,
578
- "cookiefile" : cookie_txt_file(),
579
  "prefer_ffmpeg": True,
580
  "merge_output_format": "mp4",
581
  }
@@ -591,7 +314,6 @@ class YouTubeAPI:
591
  "nocheckcertificate": True,
592
  "quiet": True,
593
  "no_warnings": True,
594
- "cookiefile" : cookie_txt_file(),
595
  "prefer_ffmpeg": True,
596
  "postprocessors": [
597
  {
@@ -613,10 +335,9 @@ class YouTubeAPI:
613
  fpath = f"downloads/{title}.mp3"
614
  return fpath
615
  elif video:
616
- direct = True
617
- downloaded_file = await loop.run_in_executor(None, lambda:video_dl(vid_id))
618
  else:
619
- direct = True
620
- downloaded_file = await loop.run_in_executor(None, lambda:audio_dl(vid_id))
621
-
622
  return downloaded_file, direct
 
1
  import asyncio
 
 
2
  import os
 
3
  import re
4
+ import json
5
+ import httpx # Make sure to import httpx
6
+ import tempfile
 
7
  import yt_dlp
8
+ from typing import Union
9
  from pyrogram.enums import MessageEntityType
10
  from pyrogram.types import Message
11
+ from youtubesearchpython.__future__ import VideosSearch
 
 
 
 
12
  from DragMusic.utils.database import is_on_off
13
  from DragMusic.utils.formatters import time_to_seconds
14
+ from typing import Union
15
+ from pyrogram.types import Message
16
+ from pyrogram.enums import MessageEntityType
17
+ from youtubesearchpython.__future__ import VideosSearch
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ def time_to_seconds(time):
21
+ stringt = str(time)
22
+ return sum(int(x) * 60**i for i, x in enumerate(reversed(stringt.split(":"))))
 
 
 
23
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
  async def shell_cmd(cmd):
26
  proc = await asyncio.create_subprocess_shell(
 
37
  return out.decode("utf-8")
38
 
39
 
40
+
41
+ async def get_stream_url(query, video=False):
42
+ api_url = "http://46.250.243.87:1470/youtube"
43
+ api_key = "1a873582a7c83342f961cc0a177b2b26"
44
+
45
+ async with httpx.AsyncClient(timeout=60) as client:
46
+ params = {"query": query, "video": video, "api_key": api_key}
47
+ response = await client.get(api_url, params=params)
48
+ if response.status_code != 200:
49
+ return ""
50
+ info = response.json()
51
+ return info.get("stream_url")
52
+
53
+
54
+
55
  class YouTubeAPI:
56
  def __init__(self):
57
  self.base = "https://www.youtube.com/watch?v="
 
59
  self.status = "https://www.youtube.com/oembed?url="
60
  self.listbase = "https://youtube.com/playlist?list="
61
  self.reg = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
  async def exists(self, link: str, videoid: Union[bool, str] = None):
64
  if videoid:
 
97
  link = self.base + link
98
  if "&" in link:
99
  link = link.split("&")[0]
100
+ results = VideosSearch(link, limit=1)
101
+ for result in (await results.next())["result"]:
102
+ title = result["title"]
103
+ duration_min = result["duration"]
104
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
105
+ vidid = result["id"]
106
+ if str(duration_min) == "None":
107
+ duration_sec = 0
108
+ else:
109
+ duration_sec = int(time_to_seconds(duration_min))
 
 
 
 
 
 
 
 
 
 
110
  return title, duration_min, duration_sec, thumbnail, vidid
111
 
112
  async def title(self, link: str, videoid: Union[bool, str] = None):
 
114
  link = self.base + link
115
  if "&" in link:
116
  link = link.split("&")[0]
117
+ results = VideosSearch(link, limit=1)
118
+ for result in (await results.next())["result"]:
119
+ title = result["title"]
120
+ return title
 
 
 
 
 
121
 
122
  async def duration(self, link: str, videoid: Union[bool, str] = None):
123
  if videoid:
124
  link = self.base + link
125
  if "&" in link:
126
  link = link.split("&")[0]
127
+ results = VideosSearch(link, limit=1)
128
+ for result in (await results.next())["result"]:
129
+ duration = result["duration"]
130
+ return duration
 
 
 
 
 
131
 
132
  async def thumbnail(self, link: str, videoid: Union[bool, str] = None):
133
  if videoid:
134
  link = self.base + link
135
  if "&" in link:
136
  link = link.split("&")[0]
137
+ results = VideosSearch(link, limit=1)
138
+ for result in (await results.next())["result"]:
139
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
140
+ return thumbnail
 
 
 
 
 
141
 
142
  async def video(self, link: str, videoid: Union[bool, str] = None):
143
  if videoid:
144
  link = self.base + link
145
  if "&" in link:
146
  link = link.split("&")[0]
147
+
148
+ return await get_stream_url(link, True)
149
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
 
151
  async def playlist(self, link, limit, user_id, videoid: Union[bool, str] = None):
152
  if videoid:
153
  link = self.listbase + link
154
  if "&" in link:
155
  link = link.split("&")[0]
 
 
 
 
156
  playlist = await shell_cmd(
157
+ f"yt-dlp -i --get-id --flat-playlist --playlist-end {limit} --skip-download {link}"
158
  )
159
  try:
160
  result = playlist.split("\n")
 
170
  link = self.base + link
171
  if "&" in link:
172
  link = link.split("&")[0]
173
+ results = VideosSearch(link, limit=1)
174
+ for result in (await results.next())["result"]:
175
+ title = result["title"]
176
+ duration_min = result["duration"]
177
+ vidid = result["id"]
178
+ yturl = result["link"]
179
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
 
 
180
  track_details = {
181
+ "title": title,
182
+ "link": yturl,
183
+ "vidid": vidid,
184
+ "duration_min": duration_min,
185
+ "thumb": thumbnail,
186
  }
187
+ return track_details, vidid
188
 
189
  async def formats(self, link: str, videoid: Union[bool, str] = None):
190
  if videoid:
191
  link = self.base + link
192
  if "&" in link:
193
  link = link.split("&")[0]
194
+ ytdl_opts = {"quiet": True}
 
 
 
 
195
  ydl = yt_dlp.YoutubeDL(ytdl_opts)
196
  with ydl:
197
  formats_available = []
 
222
  )
223
  return formats_available, link
224
 
225
+ async def slider(
226
+ self,
227
+ link: str,
228
+ query_type: int,
229
+ videoid: Union[bool, str] = None,
230
+ ):
231
  if videoid:
232
  link = self.base + link
233
  if "&" in link:
234
  link = link.split("&")[0]
235
+ a = VideosSearch(link, limit=10)
236
+ result = (await a.next()).get("result")
237
+ title = result[query_type]["title"]
238
+ duration_min = result[query_type]["duration"]
239
+ vidid = result[query_type]["id"]
240
+ thumbnail = result[query_type]["thumbnails"][0]["url"].split("?")[0]
241
+ return title, duration_min, thumbnail, vidid
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
242
 
243
  async def download(
244
  self,
 
252
  title: Union[bool, str] = None,
253
  ) -> str:
254
  if videoid:
 
255
  link = self.base + link
256
  loop = asyncio.get_running_loop()
257
 
258
+ def audio_dl():
259
+ ydl_optssx = {
260
+ "format": "bestaudio/best",
261
+ "outtmpl": "downloads/%(id)s.%(ext)s",
262
+ "geo_bypass": True,
 
 
 
 
 
 
 
263
  "nocheckcertificate": True,
264
+ "quiet": True,
265
+ "no_warnings": True,
 
 
 
266
  }
267
+ x = yt_dlp.YoutubeDL(ydl_optssx)
268
+ info = x.extract_info(link, False)
269
+ xyz = os.path.join("downloads", f"{info['id']}.{info['ext']}")
270
+ if os.path.exists(xyz):
271
+ return xyz
272
+ x.download([link])
273
+ return xyz
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
 
275
+ def video_dl():
276
+ ydl_optssx = {
277
+ "format": "(bestvideo[height<=?720][width<=?1280][ext=mp4])+(bestaudio[ext=m4a])",
278
+ "outtmpl": "downloads/%(id)s.%(ext)s",
279
+ "geo_bypass": True,
280
+ "nocheckcertificate": True,
281
+ "quiet": True,
282
+ "no_warnings": True,
283
+ }
284
+ x = yt_dlp.YoutubeDL(ydl_optssx)
285
+ info = x.extract_info(link, False)
286
+ xyz = os.path.join("downloads", f"{info['id']}.{info['ext']}")
287
+ if os.path.exists(xyz):
288
+ return xyz
289
+ x.download([link])
290
+ return xyz
291
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  def song_video_dl():
293
  formats = f"{format_id}+140"
294
  fpath = f"downloads/{title}"
 
299
  "nocheckcertificate": True,
300
  "quiet": True,
301
  "no_warnings": True,
 
302
  "prefer_ffmpeg": True,
303
  "merge_output_format": "mp4",
304
  }
 
314
  "nocheckcertificate": True,
315
  "quiet": True,
316
  "no_warnings": True,
 
317
  "prefer_ffmpeg": True,
318
  "postprocessors": [
319
  {
 
335
  fpath = f"downloads/{title}.mp3"
336
  return fpath
337
  elif video:
338
+ downloaded_file = await get_stream_url(link, True)
339
+ direct = None
340
  else:
341
+ direct = None
342
+ downloaded_file = await get_stream_url(link, False)
 
343
  return downloaded_file, direct