taslim19
commited on
Commit
·
8d58bbb
1
Parent(s):
a2c0892
fix: use temp directory for all YouTube downloads to avoid permission errors
Browse files
DragMusic/platforms/Youtube.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1 |
-
|
2 |
import asyncio
|
3 |
import os
|
4 |
import re
|
@@ -11,6 +10,8 @@ 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 |
async def shell_cmd(cmd):
|
15 |
proc = await asyncio.create_subprocess_shell(
|
16 |
cmd,
|
@@ -24,6 +25,7 @@ async def shell_cmd(cmd):
|
|
24 |
else:
|
25 |
return errorz.decode("utf-8")
|
26 |
return out.decode("utf-8")
|
|
|
27 |
class YouTubeAPI:
|
28 |
def __init__(self):
|
29 |
self.base = "https://www.youtube.com/watch?v="
|
@@ -31,6 +33,7 @@ class YouTubeAPI:
|
|
31 |
self.status = "https://www.youtube.com/oembed?url="
|
32 |
self.listbase = "https://youtube.com/playlist?list="
|
33 |
self.reg = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
|
|
|
34 |
async def exists(self, link: str, videoid: Union[bool, str] = None):
|
35 |
if videoid:
|
36 |
link = self.base + link
|
@@ -38,6 +41,7 @@ class YouTubeAPI:
|
|
38 |
return True
|
39 |
else:
|
40 |
return False
|
|
|
41 |
async def url(self, message_1: Message) -> Union[str, None]:
|
42 |
messages = [message_1]
|
43 |
if message_1.reply_to_message:
|
@@ -61,6 +65,7 @@ class YouTubeAPI:
|
|
61 |
if offset in (None,):
|
62 |
return None
|
63 |
return text[offset : offset + length]
|
|
|
64 |
async def details(self, link: str, videoid: Union[bool, str] = None):
|
65 |
if videoid:
|
66 |
link = self.base + link
|
@@ -77,6 +82,7 @@ class YouTubeAPI:
|
|
77 |
else:
|
78 |
duration_sec = int(time_to_seconds(duration_min))
|
79 |
return title, duration_min, duration_sec, thumbnail, vidid
|
|
|
80 |
async def title(self, link: str, videoid: Union[bool, str] = None):
|
81 |
if videoid:
|
82 |
link = self.base + link
|
@@ -86,6 +92,7 @@ class YouTubeAPI:
|
|
86 |
for result in (await results.next())["result"]:
|
87 |
title = result["title"]
|
88 |
return title
|
|
|
89 |
async def duration(self, link: str, videoid: Union[bool, str] = None):
|
90 |
if videoid:
|
91 |
link = self.base + link
|
@@ -95,6 +102,7 @@ class YouTubeAPI:
|
|
95 |
for result in (await results.next())["result"]:
|
96 |
duration = result["duration"]
|
97 |
return duration
|
|
|
98 |
async def thumbnail(self, link: str, videoid: Union[bool, str] = None):
|
99 |
if videoid:
|
100 |
link = self.base + link
|
@@ -104,6 +112,7 @@ class YouTubeAPI:
|
|
104 |
for result in (await results.next())["result"]:
|
105 |
thumbnail = result["thumbnails"][0]["url"].split("?")[0]
|
106 |
return thumbnail
|
|
|
107 |
async def video(self, link: str, videoid: Union[bool, str] = None):
|
108 |
if videoid:
|
109 |
link = self.base + link
|
@@ -123,6 +132,7 @@ class YouTubeAPI:
|
|
123 |
return 1, stdout.decode().split("\n")[0]
|
124 |
else:
|
125 |
return 0, stderr.decode()
|
|
|
126 |
async def playlist(self, link, limit, user_id, videoid: Union[bool, str] = None):
|
127 |
if videoid:
|
128 |
link = self.listbase + link
|
@@ -139,6 +149,7 @@ class YouTubeAPI:
|
|
139 |
except:
|
140 |
result = []
|
141 |
return result
|
|
|
142 |
async def track(self, link: str, videoid: Union[bool, str] = None):
|
143 |
if videoid:
|
144 |
link = self.base + link
|
@@ -159,6 +170,7 @@ class YouTubeAPI:
|
|
159 |
"thumb": thumbnail,
|
160 |
}
|
161 |
return track_details, vidid
|
|
|
162 |
async def formats(self, link: str, videoid: Union[bool, str] = None):
|
163 |
if videoid:
|
164 |
link = self.base + link
|
@@ -194,6 +206,7 @@ class YouTubeAPI:
|
|
194 |
}
|
195 |
)
|
196 |
return formats_available, link
|
|
|
197 |
async def slider(
|
198 |
self,
|
199 |
link: str,
|
@@ -211,6 +224,7 @@ class YouTubeAPI:
|
|
211 |
vidid = result[query_type]["id"]
|
212 |
thumbnail = result[query_type]["thumbnails"][0]["url"].split("?")[0]
|
213 |
return title, duration_min, thumbnail, vidid
|
|
|
214 |
async def get_video_info_from_bitflow(self, url: str, video: bool):
|
215 |
api_url = "https://bitflow.in/api/youtube"
|
216 |
params = {
|
@@ -226,6 +240,7 @@ class YouTubeAPI:
|
|
226 |
return response.json()
|
227 |
else:
|
228 |
return {"status": "error", "message": "Failed to fetch data from Bitflow API."}
|
|
|
229 |
async def download(
|
230 |
self,
|
231 |
link: str,
|
@@ -244,7 +259,8 @@ class YouTubeAPI:
|
|
244 |
loop = asyncio.get_running_loop()
|
245 |
bitflow_info = await self.get_video_info_from_bitflow(link, video)
|
246 |
def audio_dl(bitflow_info):
|
247 |
-
|
|
|
248 |
ydl_optssx = {
|
249 |
"format": "bestaudio/best",
|
250 |
"outtmpl": xyz,
|
@@ -259,7 +275,8 @@ class YouTubeAPI:
|
|
259 |
x.download([bitflow_info['url']])
|
260 |
return xyz
|
261 |
def video_dl(bitflow_info):
|
262 |
-
|
|
|
263 |
ydl_optssx = {
|
264 |
"format": "(bestvideo[height<=?720][width<=?1280][ext=mp4])+(bestaudio[ext=m4a])",
|
265 |
"outtmpl": xyz,
|
@@ -274,8 +291,9 @@ class YouTubeAPI:
|
|
274 |
x.download([bitflow_info['url']])
|
275 |
return xyz
|
276 |
def song_video_dl():
|
|
|
|
|
277 |
formats = f"{format_id}+140"
|
278 |
-
fpath = f"downloads/{title}"
|
279 |
ydl_optssx = {
|
280 |
"format": formats,
|
281 |
"outtmpl": fpath,
|
@@ -289,7 +307,8 @@ class YouTubeAPI:
|
|
289 |
x = yt_dlp.YoutubeDL(ydl_optssx)
|
290 |
x.download([link])
|
291 |
def song_audio_dl():
|
292 |
-
|
|
|
293 |
ydl_optssx = {
|
294 |
"format": format_id,
|
295 |
"outtmpl": fpath,
|
@@ -310,11 +329,13 @@ class YouTubeAPI:
|
|
310 |
x.download([link])
|
311 |
if songvideo:
|
312 |
await loop.run_in_executor(None, song_video_dl)
|
313 |
-
|
|
|
314 |
return fpath
|
315 |
elif songaudio:
|
316 |
await loop.run_in_executor(None, song_audio_dl)
|
317 |
-
|
|
|
318 |
return fpath
|
319 |
elif video:
|
320 |
direct = True
|
|
|
|
|
1 |
import asyncio
|
2 |
import os
|
3 |
import re
|
|
|
10 |
from youtubesearchpython.__future__ import VideosSearch
|
11 |
from DragMusic.utils.database import is_on_off
|
12 |
from DragMusic.utils.formatters import time_to_seconds
|
13 |
+
import tempfile
|
14 |
+
|
15 |
async def shell_cmd(cmd):
|
16 |
proc = await asyncio.create_subprocess_shell(
|
17 |
cmd,
|
|
|
25 |
else:
|
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="
|
|
|
33 |
self.status = "https://www.youtube.com/oembed?url="
|
34 |
self.listbase = "https://youtube.com/playlist?list="
|
35 |
self.reg = re.compile(r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])")
|
36 |
+
|
37 |
async def exists(self, link: str, videoid: Union[bool, str] = None):
|
38 |
if videoid:
|
39 |
link = self.base + link
|
|
|
41 |
return True
|
42 |
else:
|
43 |
return False
|
44 |
+
|
45 |
async def url(self, message_1: Message) -> Union[str, None]:
|
46 |
messages = [message_1]
|
47 |
if message_1.reply_to_message:
|
|
|
65 |
if offset in (None,):
|
66 |
return None
|
67 |
return text[offset : offset + length]
|
68 |
+
|
69 |
async def details(self, link: str, videoid: Union[bool, str] = None):
|
70 |
if videoid:
|
71 |
link = self.base + link
|
|
|
82 |
else:
|
83 |
duration_sec = int(time_to_seconds(duration_min))
|
84 |
return title, duration_min, duration_sec, thumbnail, vidid
|
85 |
+
|
86 |
async def title(self, link: str, videoid: Union[bool, str] = None):
|
87 |
if videoid:
|
88 |
link = self.base + link
|
|
|
92 |
for result in (await results.next())["result"]:
|
93 |
title = result["title"]
|
94 |
return title
|
95 |
+
|
96 |
async def duration(self, link: str, videoid: Union[bool, str] = None):
|
97 |
if videoid:
|
98 |
link = self.base + link
|
|
|
102 |
for result in (await results.next())["result"]:
|
103 |
duration = result["duration"]
|
104 |
return duration
|
105 |
+
|
106 |
async def thumbnail(self, link: str, videoid: Union[bool, str] = None):
|
107 |
if videoid:
|
108 |
link = self.base + link
|
|
|
112 |
for result in (await results.next())["result"]:
|
113 |
thumbnail = result["thumbnails"][0]["url"].split("?")[0]
|
114 |
return thumbnail
|
115 |
+
|
116 |
async def video(self, link: str, videoid: Union[bool, str] = None):
|
117 |
if videoid:
|
118 |
link = self.base + link
|
|
|
132 |
return 1, stdout.decode().split("\n")[0]
|
133 |
else:
|
134 |
return 0, stderr.decode()
|
135 |
+
|
136 |
async def playlist(self, link, limit, user_id, videoid: Union[bool, str] = None):
|
137 |
if videoid:
|
138 |
link = self.listbase + link
|
|
|
149 |
except:
|
150 |
result = []
|
151 |
return result
|
152 |
+
|
153 |
async def track(self, link: str, videoid: Union[bool, str] = None):
|
154 |
if videoid:
|
155 |
link = self.base + link
|
|
|
170 |
"thumb": thumbnail,
|
171 |
}
|
172 |
return track_details, vidid
|
173 |
+
|
174 |
async def formats(self, link: str, videoid: Union[bool, str] = None):
|
175 |
if videoid:
|
176 |
link = self.base + link
|
|
|
206 |
}
|
207 |
)
|
208 |
return formats_available, link
|
209 |
+
|
210 |
async def slider(
|
211 |
self,
|
212 |
link: str,
|
|
|
224 |
vidid = result[query_type]["id"]
|
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 = {
|
|
|
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,
|
|
|
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 |
ydl_optssx = {
|
265 |
"format": "bestaudio/best",
|
266 |
"outtmpl": xyz,
|
|
|
275 |
x.download([bitflow_info['url']])
|
276 |
return xyz
|
277 |
def video_dl(bitflow_info):
|
278 |
+
temp_dir = tempfile.gettempdir()
|
279 |
+
xyz = os.path.join(temp_dir, f"{bitflow_info['videoid']}.{bitflow_info['ext']}")
|
280 |
ydl_optssx = {
|
281 |
"format": "(bestvideo[height<=?720][width<=?1280][ext=mp4])+(bestaudio[ext=m4a])",
|
282 |
"outtmpl": xyz,
|
|
|
291 |
x.download([bitflow_info['url']])
|
292 |
return xyz
|
293 |
def song_video_dl():
|
294 |
+
temp_dir = tempfile.gettempdir()
|
295 |
+
fpath = os.path.join(temp_dir, f"{title}")
|
296 |
formats = f"{format_id}+140"
|
|
|
297 |
ydl_optssx = {
|
298 |
"format": formats,
|
299 |
"outtmpl": fpath,
|
|
|
307 |
x = yt_dlp.YoutubeDL(ydl_optssx)
|
308 |
x.download([link])
|
309 |
def song_audio_dl():
|
310 |
+
temp_dir = tempfile.gettempdir()
|
311 |
+
fpath = os.path.join(temp_dir, f"{title}.%(ext)s")
|
312 |
ydl_optssx = {
|
313 |
"format": format_id,
|
314 |
"outtmpl": fpath,
|
|
|
329 |
x.download([link])
|
330 |
if songvideo:
|
331 |
await loop.run_in_executor(None, song_video_dl)
|
332 |
+
temp_dir = tempfile.gettempdir()
|
333 |
+
fpath = os.path.join(temp_dir, f"{title}.mp4")
|
334 |
return fpath
|
335 |
elif songaudio:
|
336 |
await loop.run_in_executor(None, song_audio_dl)
|
337 |
+
temp_dir = tempfile.gettempdir()
|
338 |
+
fpath = os.path.join(temp_dir, f"{title}.mp3")
|
339 |
return fpath
|
340 |
elif video:
|
341 |
direct = True
|