xdragxt commited on
Commit
cc6cb05
·
verified ·
1 Parent(s): 742bfd7

Update Devine/platforms/Youtube.py

Browse files
Files changed (1) hide show
  1. Devine/platforms/Youtube.py +74 -117
Devine/platforms/Youtube.py CHANGED
@@ -1,51 +1,16 @@
1
  import asyncio
2
- import glob
3
  import os
4
- import random
5
  import re
 
 
6
  from typing import Union
7
-
8
  from pyrogram.enums import MessageEntityType
9
  from pyrogram.types import Message
10
  from youtubesearchpython.__future__ import VideosSearch
11
- from yt_dlp import YoutubeDL
12
-
13
- import config
14
  from Devine.utils.database import is_on_off
15
  from Devine.utils.formatters import time_to_seconds
16
-
17
- def cookies():
18
- folder_path = f"{os.getcwd()}/cookies"
19
- txt_files = glob.glob(os.path.join(folder_path, "*.txt"))
20
- if not txt_files:
21
- raise FileNotFoundError("No .txt files found in the specified folder.")
22
- cookie_txt_file = random.choice(txt_files)
23
- return f"""cookies/{str(cookie_txt_file).split("/")[-1]}"""
24
-
25
-
26
- def get_ytdl_options(ytdl_opts: Union[str, dict, list], commandline: bool = True) -> Union[str, dict, list]:
27
- token_data = os.getenv("TOKEN_DATA")
28
-
29
- if isinstance(ytdl_opts, list):
30
- if token_data:
31
- ytdl_opts += ["--username" if commandline else "username", "oauth2", "--password" if commandline else "password", "''"]
32
- else:
33
- ytdl_opts += ["--cookies" if commandline else "cookiefile", cookies()]
34
-
35
- elif isinstance(ytdl_opts, str):
36
- if token_data:
37
- ytdl_opts += "--username oauth2 --password '' " if commandline else "username oauth2 password '' "
38
- else:
39
- ytdl_opts += f"--cookies {cookies()}" if commandline else f"cookiefile {cookies()}"
40
-
41
- elif isinstance(ytdl_opts, dict):
42
- if token_data:
43
- ytdl_opts.update({"username": "oauth2", "password": ""})
44
- else:
45
- ytdl_opts["cookiefile"] = cookies()
46
-
47
- return ytdl_opts
48
-
49
 
50
  async def shell_cmd(cmd):
51
  proc = await asyncio.create_subprocess_shell(
@@ -61,7 +26,6 @@ async def shell_cmd(cmd):
61
  return errorz.decode("utf-8")
62
  return out.decode("utf-8")
63
 
64
-
65
  class YouTubeAPI:
66
  def __init__(self):
67
  self.base = "https://www.youtube.com/watch?v="
@@ -154,16 +118,12 @@ class YouTubeAPI:
154
  link = self.base + link
155
  if "&" in link:
156
  link = link.split("&")[0]
157
- cmd = [
158
  "yt-dlp",
159
  "-g",
160
  "-f",
161
  "best[height<=?720][width<=?1280]",
162
  f"{link}",
163
- ]
164
- cmd = get_ytdl_options(cmd)
165
- proc = await asyncio.create_subprocess_exec(
166
- *cmd,
167
  stdout=asyncio.subprocess.PIPE,
168
  stderr=asyncio.subprocess.PIPE,
169
  )
@@ -178,11 +138,9 @@ class YouTubeAPI:
178
  link = self.listbase + link
179
  if "&" in link:
180
  link = link.split("&")[0]
181
-
182
- cmd = get_ytdl_options(
183
  f"yt-dlp -i --get-id --flat-playlist --playlist-end {limit} --skip-download {link}"
184
  )
185
- playlist = await shell_cmd(cmd)
186
  try:
187
  result = playlist.split("\n")
188
  for key in result:
@@ -218,29 +176,24 @@ class YouTubeAPI:
218
  link = self.base + link
219
  if "&" in link:
220
  link = link.split("&")[0]
221
-
222
- ytdl_opts = {
223
- "quiet": True,
224
- }
225
- ytdl_opts = get_ytdl_options(ytdl_opts, False)
226
-
227
- ydl = YoutubeDL(ytdl_opts)
228
  with ydl:
229
  formats_available = []
230
  r = ydl.extract_info(link, download=False)
231
  for format in r["formats"]:
232
  try:
233
  str(format["format"])
234
- except Exception:
235
  continue
236
- if "dash" not in str(format["format"]).lower():
237
  try:
238
  format["format"]
239
  format["filesize"]
240
  format["format_id"]
241
  format["ext"]
242
  format["format_note"]
243
- except KeyError:
244
  continue
245
  formats_available.append(
246
  {
@@ -272,6 +225,22 @@ class YouTubeAPI:
272
  thumbnail = result[query_type]["thumbnails"][0]["url"].split("?")[0]
273
  return title, duration_min, thumbnail, vidid
274
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
275
  async def download(
276
  self,
277
  link: str,
@@ -285,49 +254,64 @@ class YouTubeAPI:
285
  ) -> str:
286
  if videoid:
287
  link = self.base + link
 
 
288
  loop = asyncio.get_running_loop()
289
-
290
- def audio_dl():
 
 
 
 
 
 
 
 
 
 
 
291
  ydl_optssx = {
292
  "format": "bestaudio/best",
293
- "outtmpl": "downloads/%(id)s.%(ext)s",
294
  "geo_bypass": True,
295
  "nocheckcertificate": True,
296
  "quiet": True,
297
  "no_warnings": True,
298
  }
299
- ydl_optssx = get_ytdl_options(ydl_optssx, False)
300
-
301
- x = YoutubeDL(ydl_optssx)
302
- info = x.extract_info(link, False)
303
- xyz = os.path.join("downloads", f"{info['id']}.{info['ext']}")
304
  if os.path.exists(xyz):
305
  return xyz
306
- x.download([link])
307
  return xyz
308
-
309
- def video_dl():
 
 
 
 
 
 
 
 
 
 
310
  ydl_optssx = {
311
  "format": "(bestvideo[height<=?720][width<=?1280][ext=mp4])+(bestaudio[ext=m4a])",
312
- "outtmpl": "downloads/%(id)s.%(ext)s",
313
  "geo_bypass": True,
314
  "nocheckcertificate": True,
315
  "quiet": True,
316
  "no_warnings": True,
317
  }
318
- ydl_optssx = get_ytdl_options(ydl_optssx, False)
319
-
320
- x = YoutubeDL(ydl_optssx)
321
- info = x.extract_info(link, False)
322
- xyz = os.path.join("downloads", f"{info['id']}.{info['ext']}")
323
  if os.path.exists(xyz):
324
  return xyz
325
- x.download([link])
326
  return xyz
327
-
328
  def song_video_dl():
 
 
329
  formats = f"{format_id}+140"
330
- fpath = f"downloads/{title}"
331
  ydl_optssx = {
332
  "format": formats,
333
  "outtmpl": fpath,
@@ -338,13 +322,11 @@ class YouTubeAPI:
338
  "prefer_ffmpeg": True,
339
  "merge_output_format": "mp4",
340
  }
341
- ydl_optssx = get_ytdl_options(ydl_optssx, False)
342
-
343
- x = YoutubeDL(ydl_optssx)
344
  x.download([link])
345
-
346
  def song_audio_dl():
347
- fpath = f"downloads/{title}.%(ext)s"
 
348
  ydl_optssx = {
349
  "format": format_id,
350
  "outtmpl": fpath,
@@ -361,47 +343,22 @@ class YouTubeAPI:
361
  }
362
  ],
363
  }
364
- ydl_optssx = get_ytdl_options(ydl_optssx, False)
365
-
366
- x = YoutubeDL(ydl_optssx)
367
  x.download([link])
368
-
369
  if songvideo:
370
  await loop.run_in_executor(None, song_video_dl)
371
- fpath = f"downloads/{title}.mp4"
 
372
  return fpath
373
  elif songaudio:
374
  await loop.run_in_executor(None, song_audio_dl)
375
- fpath = f"downloads/{title}.mp3"
 
376
  return fpath
377
  elif video:
378
- if await is_on_off(config.YTDOWNLOADER):
379
- direct = True
380
- downloaded_file = await loop.run_in_executor(None, video_dl)
381
- else:
382
- command = [
383
- "yt-dlp",
384
- "-g",
385
- "-f",
386
- "best[height<=?720][width<=?1280]",
387
- link,
388
- ]
389
- command = get_ytdl_options(command)
390
-
391
- proc = await asyncio.create_subprocess_exec(
392
- *command,
393
- stdout=asyncio.subprocess.PIPE,
394
- stderr=asyncio.subprocess.PIPE,
395
- )
396
- stdout, stderr = await proc.communicate()
397
-
398
- if stdout:
399
- downloaded_file = stdout.decode().split("\n")[0]
400
- direct = None
401
- else:
402
- return
403
  else:
404
  direct = True
405
- downloaded_file = await loop.run_in_executor(None, audio_dl)
406
-
407
- 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
  from typing import Union
7
+ import yt_dlp
8
  from pyrogram.enums import MessageEntityType
9
  from pyrogram.types import Message
10
  from youtubesearchpython.__future__ import VideosSearch
 
 
 
11
  from Devine.utils.database import is_on_off
12
  from Devine.utils.formatters import time_to_seconds
13
+ import tempfile
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
  async def shell_cmd(cmd):
16
  proc = await asyncio.create_subprocess_shell(
 
26
  return errorz.decode("utf-8")
27
  return out.decode("utf-8")
28
 
 
29
  class YouTubeAPI:
30
  def __init__(self):
31
  self.base = "https://www.youtube.com/watch?v="
 
118
  link = self.base + link
119
  if "&" in link:
120
  link = link.split("&")[0]
121
+ proc = await asyncio.create_subprocess_exec(
122
  "yt-dlp",
123
  "-g",
124
  "-f",
125
  "best[height<=?720][width<=?1280]",
126
  f"{link}",
 
 
 
 
127
  stdout=asyncio.subprocess.PIPE,
128
  stderr=asyncio.subprocess.PIPE,
129
  )
 
138
  link = self.listbase + link
139
  if "&" in link:
140
  link = link.split("&")[0]
141
+ playlist = await shell_cmd(
 
142
  f"yt-dlp -i --get-id --flat-playlist --playlist-end {limit} --skip-download {link}"
143
  )
 
144
  try:
145
  result = playlist.split("\n")
146
  for key in result:
 
176
  link = self.base + link
177
  if "&" in link:
178
  link = link.split("&")[0]
179
+ ytdl_opts = {"quiet": True}
180
+ ydl = yt_dlp.YoutubeDL(ytdl_opts)
 
 
 
 
 
181
  with ydl:
182
  formats_available = []
183
  r = ydl.extract_info(link, download=False)
184
  for format in r["formats"]:
185
  try:
186
  str(format["format"])
187
+ except:
188
  continue
189
+ if not "dash" in str(format["format"]).lower():
190
  try:
191
  format["format"]
192
  format["filesize"]
193
  format["format_id"]
194
  format["ext"]
195
  format["format_note"]
196
+ except:
197
  continue
198
  formats_available.append(
199
  {
 
225
  thumbnail = result[query_type]["thumbnails"][0]["url"].split("?")[0]
226
  return title, duration_min, thumbnail, vidid
227
 
228
+ async def get_video_info_from_bitflow(self, url: str, video: bool):
229
+ api_url = "https://bitflow.in/api/youtube"
230
+ params = {
231
+ "query": url,
232
+ "format": "video" if video else "audio",
233
+ "download": True,
234
+ "api_key": "1spiderkey2"
235
+ }
236
+
237
+ async with httpx.AsyncClient() as client:
238
+ response = await client.get(api_url, params=params, timeout=150)
239
+ if response.status_code == 200:
240
+ return response.json()
241
+ else:
242
+ return {"status": "error", "message": "Failed to fetch data from Bitflow API."}
243
+
244
  async def download(
245
  self,
246
  link: str,
 
254
  ) -> str:
255
  if videoid:
256
  link = self.base + link
257
+ if "&" in link:
258
+ link = link.split("&")[0]
259
  loop = asyncio.get_running_loop()
260
+ bitflow_info = await self.get_video_info_from_bitflow(link, video)
261
+ def audio_dl(bitflow_info):
262
+ temp_dir = tempfile.gettempdir()
263
+ xyz = os.path.join(temp_dir, f"{bitflow_info['videoid']}.{bitflow_info['ext']}")
264
+ url = bitflow_info['url']
265
+ # If the url is not a YouTube link, download directly
266
+ if not (url.startswith('http') and ('youtube.com' in url or 'youtu.be' in url)):
267
+ import httpx
268
+ with httpx.Client() as client:
269
+ r = client.get(url)
270
+ with open(xyz, "wb") as f:
271
+ f.write(r.content)
272
+ return xyz
273
  ydl_optssx = {
274
  "format": "bestaudio/best",
275
+ "outtmpl": xyz,
276
  "geo_bypass": True,
277
  "nocheckcertificate": True,
278
  "quiet": True,
279
  "no_warnings": True,
280
  }
281
+ x = yt_dlp.YoutubeDL(ydl_optssx)
 
 
 
 
282
  if os.path.exists(xyz):
283
  return xyz
284
+ x.download([url])
285
  return xyz
286
+ def video_dl(bitflow_info):
287
+ temp_dir = tempfile.gettempdir()
288
+ xyz = os.path.join(temp_dir, f"{bitflow_info['videoid']}.{bitflow_info['ext']}")
289
+ url = bitflow_info['url']
290
+ # If the url is not a YouTube link, download directly
291
+ if not (url.startswith('http') and ('youtube.com' in url or 'youtu.be' in url)):
292
+ import httpx
293
+ with httpx.Client() as client:
294
+ r = client.get(url)
295
+ with open(xyz, "wb") as f:
296
+ f.write(r.content)
297
+ return xyz
298
  ydl_optssx = {
299
  "format": "(bestvideo[height<=?720][width<=?1280][ext=mp4])+(bestaudio[ext=m4a])",
300
+ "outtmpl": xyz,
301
  "geo_bypass": True,
302
  "nocheckcertificate": True,
303
  "quiet": True,
304
  "no_warnings": True,
305
  }
306
+ x = yt_dlp.YoutubeDL(ydl_optssx)
 
 
 
 
307
  if os.path.exists(xyz):
308
  return xyz
309
+ x.download([url])
310
  return xyz
 
311
  def song_video_dl():
312
+ temp_dir = tempfile.gettempdir()
313
+ fpath = os.path.join(temp_dir, f"{title}")
314
  formats = f"{format_id}+140"
 
315
  ydl_optssx = {
316
  "format": formats,
317
  "outtmpl": fpath,
 
322
  "prefer_ffmpeg": True,
323
  "merge_output_format": "mp4",
324
  }
325
+ x = yt_dlp.YoutubeDL(ydl_optssx)
 
 
326
  x.download([link])
 
327
  def song_audio_dl():
328
+ temp_dir = tempfile.gettempdir()
329
+ fpath = os.path.join(temp_dir, f"{title}.%(ext)s")
330
  ydl_optssx = {
331
  "format": format_id,
332
  "outtmpl": fpath,
 
343
  }
344
  ],
345
  }
346
+ x = yt_dlp.YoutubeDL(ydl_optssx)
 
 
347
  x.download([link])
 
348
  if songvideo:
349
  await loop.run_in_executor(None, song_video_dl)
350
+ temp_dir = tempfile.gettempdir()
351
+ fpath = os.path.join(temp_dir, f"{title}.mp4")
352
  return fpath
353
  elif songaudio:
354
  await loop.run_in_executor(None, song_audio_dl)
355
+ temp_dir = tempfile.gettempdir()
356
+ fpath = os.path.join(temp_dir, f"{title}.mp3")
357
  return fpath
358
  elif video:
359
+ direct = True
360
+ downloaded_file = await loop.run_in_executor(None, video_dl, bitflow_info)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  else:
362
  direct = True
363
+ downloaded_file = await loop.run_in_executor(None, audio_dl, bitflow_info)
364
+ return downloaded_file, direct