taslim19 commited on
Commit
398389e
·
1 Parent(s): f11256b

refactor: Revert to simpler, direct yt-dlp implementation in Youtube.py

Browse files
DragMusic/platforms/Youtube.py CHANGED
@@ -1,7 +1,7 @@
1
  import asyncio
2
- import json
3
  import re
4
- from typing import Dict, List, Optional, Tuple, Union
5
 
6
  import yt_dlp
7
  from pyrogram.enums import MessageEntityType
@@ -9,261 +9,345 @@ 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.downloader import yt_dlp_download, download_audio_concurrent
13
- from DragMusic.utils.errors import capture_err
14
  from DragMusic.utils.formatters import time_to_seconds
15
 
16
- cookies_file = "cookies.txt"
17
- _cache = {}
18
 
19
-
20
- @capture_err
21
- async def shell_cmd(cmd: str) -> str:
22
  proc = await asyncio.create_subprocess_shell(
23
- cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
 
 
24
  )
25
- out, err = await proc.communicate()
26
- return (out or err).decode()
27
-
28
-
29
- @capture_err
30
- async def cached_youtube_search(query: str) -> List[Dict]:
31
- if query in _cache:
32
- return _cache[query]
33
- search = VideosSearch(query, limit=1)
34
- results = await search.next()
35
- result_data = results.get("result", [])
36
- if result_data:
37
- _cache[query] = result_data
38
- return result_data
39
 
40
 
41
  class YouTubeAPI:
42
- def __init__(self) -> None:
43
- self.base_url = "https://www.youtube.com/watch?v="
44
- self.playlist_url = "https://youtube.com/playlist?list="
45
- self._url_pattern = re.compile(r"(?:youtube\.com|youtu\.be)")
46
-
47
- def _prepare_link(self, link: str, videoid: Union[str, bool, None] = None) -> str:
48
- if isinstance(videoid, str) and videoid.strip():
49
- link = self.base_url + videoid.strip()
50
- if "youtu.be" in link:
51
- link = self.base_url + link.split("/")[-1].split("?")[0]
52
- elif "youtube.com/shorts/" in link or "youtube.com/live/" in link:
53
- link = self.base_url + link.split("/")[-1].split("?")[0]
54
- return link.split("&")[0]
55
 
56
- @capture_err
57
- async def exists(self, link: str, videoid: Union[str, bool, None] = None) -> bool:
58
- return bool(self._url_pattern.search(self._prepare_link(link, videoid)))
59
-
60
- @capture_err
61
- async def url(self, message: Message) -> Optional[str]:
62
- msgs = [message] + ([message.reply_to_message] if message.reply_to_message else [])
63
- for msg in msgs:
64
- text = msg.text or msg.caption or ""
65
- entities = msg.entities or msg.caption_entities or []
66
- for ent in entities:
67
- if ent.type == MessageEntityType.URL:
68
- return text[ent.offset : ent.offset + ent.length]
69
- if ent.type == MessageEntityType.TEXT_LINK:
70
- return ent.url
71
- return None
72
-
73
- @capture_err
74
- async def _fetch_video_info(self, query: str, *, use_cache: bool = True) -> Optional[Dict]:
75
- if use_cache and not query.startswith("http"):
76
- result = await cached_youtube_search(query)
77
  else:
78
- search = VideosSearch(query, limit=1)
79
- result = (await search.next()).get("result", [])
80
- return result[0] if result else None
81
-
82
- @capture_err
83
- async def is_live(self, link: str) -> bool:
84
- prepared = self._prepare_link(link)
85
- proc = await asyncio.create_subprocess_exec(
86
- "yt-dlp", "--cookies", cookies_file, "--dump-json", prepared,
87
- stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
88
- )
89
- stdout, _ = await proc.communicate()
90
- if not stdout:
91
- return False
92
- try:
93
- info = json.loads(stdout.decode())
94
- return bool(info.get("is_live"))
95
- except json.JSONDecodeError:
96
  return False
97
 
98
- @capture_err
99
- async def details(self, link: str, videoid: Union[str, bool, None] = None) -> Tuple[str, Optional[str], int, str, str]:
100
- info = await self._fetch_video_info(self._prepare_link(link, videoid))
101
- if not info:
102
- raise ValueError("Video not found")
103
- duration_text = info.get("duration")
104
- duration_sec = int(time_to_seconds(duration_text)) if duration_text else 0
105
- thumb = (info.get("thumbnail") or info.get("thumbnails", [{}])[0].get("url", "")).split("?")[0]
106
- return (
107
- info.get("title", ""),
108
- duration_text,
109
- duration_sec,
110
- thumb,
111
- info.get("id", ""),
112
- )
 
 
 
 
 
 
 
 
113
 
114
- @capture_err
115
- async def title(self, link: str, videoid: Union[str, bool, None] = None) -> str:
116
- info = await self._fetch_video_info(self._prepare_link(link, videoid))
117
- return info.get("title", "") if info else ""
 
 
 
 
 
 
 
 
 
 
 
 
118
 
119
- @capture_err
120
- async def duration(self, link: str, videoid: Union[str, bool, None] = None) -> Optional[str]:
121
- info = await self._fetch_video_info(self._prepare_link(link, videoid))
122
- return info.get("duration") if info else None
 
 
 
 
 
123
 
124
- @capture_err
125
- async def thumbnail(self, link: str, videoid: Union[str, bool, None] = None) -> str:
126
- info = await self._fetch_video_info(self._prepare_link(link, videoid))
127
- return (info.get("thumbnail") or info.get("thumbnails", [{}])[0].get("url", "")).split("?")[0] if info else ""
 
 
 
 
 
128
 
129
- @capture_err
130
- async def video(self, link: str, videoid: Union[str, bool, None] = None) -> Tuple[int, str]:
131
- link = self._prepare_link(link, videoid)
 
 
 
 
 
 
 
 
 
 
 
 
132
  proc = await asyncio.create_subprocess_exec(
133
- "yt-dlp", "--cookies", cookies_file, "-g", "-f", "best[height<=?720][width<=?1280]",
134
- link, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
 
 
 
 
 
 
 
135
  )
136
  stdout, stderr = await proc.communicate()
137
- return (1, stdout.decode().split("\n")[0]) if stdout else (0, stderr.decode())
 
 
 
138
 
139
- @capture_err
140
- async def playlist(self, link: str, limit: int, user_id, videoid: Union[str, bool, None] = None) -> List[str]:
141
  if videoid:
142
- link = self.playlist_url + str(videoid)
143
- link = link.split("&")[0]
144
- cmd = (
145
- f"yt-dlp --cookies {cookies_file} -i --get-id --flat-playlist "
146
- f"--playlist-end {limit} --skip-download {link}"
147
  )
148
- data = await shell_cmd(cmd)
149
- return [item for item in data.strip().split("\n") if item]
150
-
151
- @capture_err
152
- async def track(self, link: str, videoid: Union[str, bool, None] = None) -> Tuple[Dict, str]:
153
  try:
154
- info = await self._fetch_video_info(self._prepare_link(link, videoid))
155
- if not info:
156
- raise ValueError("Track not found via API")
157
- except Exception:
158
- prepared = self._prepare_link(link, videoid)
159
- proc = await asyncio.create_subprocess_exec(
160
- "yt-dlp", "--cookies", cookies_file, "--dump-json", prepared,
161
- stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
162
- )
163
- stdout, _ = await proc.communicate()
164
- if not stdout:
165
- raise ValueError("Track not found (yt-dlp fallback)")
166
- try:
167
- info = json.loads(stdout.decode())
168
- except json.JSONDecodeError:
169
- raise ValueError("Failed to parse yt-dlp output")
170
 
171
- thumb = (info.get("thumbnail") or info.get("thumbnails", [{}])[0].get("url", "")).split("?")[0]
172
- details = {
173
- "title": info.get("title", ""),
174
- "link": info.get("webpage_url", self._prepare_link(link, videoid)),
175
- "vidid": info.get("id", ""),
176
- "duration_min": info.get("duration") if isinstance(info.get("duration"), str) else None,
177
- "thumb": thumb,
 
 
 
 
 
 
 
 
 
 
 
178
  }
179
- return details, info.get("id", "")
180
 
181
- @capture_err
182
- async def formats(self, link: str, videoid: Union[str, bool, None] = None) -> Tuple[List[Dict], str]:
183
- link = self._prepare_link(link, videoid)
184
- opts = {"quiet": True, "cookiefile": cookies_file}
185
- formats: List[Dict] = []
186
- try:
187
- with yt_dlp.YoutubeDL(opts) as ydl:
188
- info = ydl.extract_info(link, download=False)
189
- for fmt in info.get("formats", []):
190
- if "dash" in fmt.get("format", "").lower():
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  continue
192
- if all(k in fmt for k in ("format", "filesize", "format_id", "ext", "format_note")):
193
- formats.append({
194
- "format": fmt["format"],
195
- "filesize": fmt["filesize"],
196
- "format_id": fmt["format_id"],
197
- "ext": fmt["ext"],
198
- "format_note": fmt["format_note"],
199
  "yturl": link,
200
- })
201
- except Exception as e:
202
- print(f"[formats()] yt-dlp error: {e}")
203
- return formats, link
204
 
205
- @capture_err
206
- async def slider(self, link: str, query_type: int, videoid: Union[str, bool, None] = None) -> Tuple[str, Optional[str], str, str]:
207
- search = VideosSearch(self._prepare_link(link, videoid), limit=10)
208
- results = (await search.next()).get("result", [])
209
- if not results or query_type >= len(results):
210
- raise IndexError(f"Query type index {query_type} out of range (found {len(results)} results)")
211
- res = results[query_type]
212
- return (
213
- res.get("title", ""),
214
- res.get("duration"),
215
- res.get("thumbnails", [{}])[0].get("url", "").split("?")[0],
216
- res.get("id", ""),
217
- )
 
 
 
 
218
 
219
- @capture_err
220
  async def download(
221
  self,
222
  link: str,
223
  mystic,
224
- *,
225
- video: Union[bool, str, None] = None,
226
- videoid: Union[str, bool, None] = None,
227
- songaudio: Union[bool, str, None] = None,
228
- songvideo: Union[bool, str, None] = None,
229
- format_id: Union[bool, str, None] = None,
230
- title: Union[bool, str, None] = None,
231
- ) -> Union[Tuple[str, Optional[bool]], Tuple[None, None]]:
232
- link = self._prepare_link(link, videoid)
 
233
 
234
- if songvideo:
235
- path = await yt_dlp_download(link, type="song_video", format_id=format_id, title=title)
236
- return (path, True) if path else (None, None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
 
238
- if songaudio:
239
- path = await yt_dlp_download(link, type="song_audio", format_id=format_id, title=title)
240
- return (path, True) if path else (None, None)
 
 
 
 
 
 
 
 
 
 
 
 
 
241
 
242
- if video:
243
- if await self.is_live(link):
244
- status, stream_url = await self.video(link)
245
- if status == 1:
246
- return stream_url, None
247
- raise ValueError("Unable to fetch live stream link")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  if await is_on_off(1):
249
- path = await yt_dlp_download(link, type="video")
250
- return (path, True) if path else (None, None)
251
  else:
252
  proc = await asyncio.create_subprocess_exec(
253
  "yt-dlp",
254
  "--cookies",
255
- cookies_file,
256
  "-g",
257
  "-f",
258
  "best[height<=?720][width<=?1280]",
259
- link,
260
  stdout=asyncio.subprocess.PIPE,
261
  stderr=asyncio.subprocess.PIPE,
262
  )
263
- stdout, _ = await proc.communicate()
264
  if stdout:
265
- return stdout.decode().split("\n")[0], None
266
- return None, None
267
-
268
- path = await download_audio_concurrent(link)
269
- return (path, True) if path else (None, None)
 
 
 
 
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
 
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):
 
 
16
  proc = await asyncio.create_subprocess_shell(
17
+ cmd,
18
+ stdout=asyncio.subprocess.PIPE,
19
+ stderr=asyncio.subprocess.PIPE,
20
  )
21
+ out, errorz = await proc.communicate()
22
+ if errorz:
23
+ if "unavailable videos are hidden" in (errorz.decode("utf-8")).lower():
24
+ return out.decode("utf-8")
25
+ else:
26
+ return errorz.decode("utf-8")
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)"
34
+ self.status = "https://www.youtube.com/oembed?url="
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):
42
+ return True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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)
50
+ text = ""
51
+ offset = None
52
+ length = None
53
+ for message in messages:
54
+ if offset:
55
+ break
56
+ if message.entities:
57
+ for entity in message.entities:
58
+ if entity.type == MessageEntityType.URL:
59
+ text = message.text or message.caption
60
+ offset, length = entity.offset, entity.length
61
+ break
62
+ elif message.caption_entities:
63
+ for entity in message.caption_entities:
64
+ if entity.type == MessageEntityType.TEXT_LINK:
65
+ return entity.url
66
+ if offset in (None,):
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:
74
+ link = link.split("&")[0]
75
+ results = VideosSearch(link, limit=1)
76
+ for result in (await results.next())["result"]:
77
+ title = result["title"]
78
+ duration_min = result["duration"]
79
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
80
+ vidid = result["id"]
81
+ if str(duration_min) == "None":
82
+ duration_sec = 0
83
+ else:
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:
91
+ link = link.split("&")[0]
92
+ results = VideosSearch(link, limit=1)
93
+ for result in (await results.next())["result"]:
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:
101
+ link = link.split("&")[0]
102
+ results = VideosSearch(link, limit=1)
103
+ for result in (await results.next())["result"]:
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:
111
+ link = link.split("&")[0]
112
+ results = VideosSearch(link, limit=1)
113
+ for result in (await results.next())["result"]:
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
  )
133
  stdout, stderr = await proc.communicate()
134
+ if stdout:
135
+ return 1, stdout.decode().split("\n")[0]
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
+ {
203
+ "format": format["format"],
204
+ "filesize": format["filesize"],
205
+ "format_id": format["format_id"],
206
+ "ext": format["ext"],
207
+ "format_note": format["format_note"],
208
  "yturl": link,
209
+ }
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
221
+ if "&" in link:
222
+ link = link.split("&")[0]
223
+ a = VideosSearch(link, limit=10)
224
+ result = (await a.next()).get("result")
225
+ title = result[query_type]["title"]
226
+ duration_min = result[query_type]["duration"]
227
+ vidid = result[query_type]["id"]
228
+ thumbnail = result[query_type]["thumbnails"][0]["url"].split("?")[0]
229
+ return title, duration_min, thumbnail, vidid
230
 
 
231
  async def download(
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,
308
+ "prefer_ffmpeg": True,
309
+ "postprocessors": [
310
+ {
311
+ "key": "FFmpegExtractAudio",
312
+ "preferredcodec": "mp3",
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
DragMusic/plugins/play/play.py CHANGED
@@ -1,83 +1,90 @@
1
  import random
2
  import string
3
- import asyncio
4
 
5
  from pyrogram import filters
6
- from pyrogram.errors import FloodWait, RandomIdDuplicate
7
  from pyrogram.types import InlineKeyboardMarkup, InputMediaPhoto, Message
8
  from pytgcalls.exceptions import NoActiveGroupCall
9
 
10
  import config
11
- from config import BANNED_USERS, lyrical, AYU
12
- from DragMusic import Apple, Resso, SoundCloud, Spotify, Telegram, YouTube, app
13
- from DragMusic.core.call import Drag
14
- from DragMusic.utils import seconds_to_min, time_to_seconds
15
- from DragMusic.utils.channelplay import get_channeplayCB
16
- from DragMusic.utils.decorators.language import languageCB
17
- from DragMusic.utils.decorators.play import PlayWrapper
18
- from DragMusic.utils.errors import capture_err, capture_callback_err
19
- from DragMusic.utils.formatters import formats
20
- from DragMusic.utils.inline import (
21
  botplaylist_markup,
22
  livestream_markup,
23
  playlist_markup,
24
  slider_markup,
25
  track_markup,
26
  )
27
- from DragMusic.utils.logger import play_logs
28
- from DragMusic.utils.stream.stream import stream
 
29
 
30
 
31
  @app.on_message(
32
- filters.command([
33
- "play", "vplay", "cplay", "cvplay",
34
- "playforce", "vplayforce", "cplayforce", "cvplayforce"
35
- ]) & filters.group & ~BANNED_USERS
 
 
 
 
 
 
 
 
 
 
36
  )
37
  @PlayWrapper
38
- @capture_err
39
- async def play_command(client, message: Message, _, chat_id, video, channel, playmode, url, fplay):
40
- try:
41
- mystic = await message.reply_text(
42
- _["play_2"].format(channel) if channel else random.choice(AYU)
43
- )
44
- except FloodWait as e:
45
- await asyncio.sleep(e.value)
46
- mystic = await message.reply_text(
47
- _["play_2"].format(channel) if channel else random.choice(AYU)
48
- )
49
- except RandomIdDuplicate:
50
- mystic = await app.send_message(
51
- message.chat.id,
52
- _["play_2"].format(channel) if channel else random.choice(AYU)
53
- )
54
-
55
- plist_id, plist_type, spotify, slider = None, None, None, None
56
  user_id = message.from_user.id
57
  user_name = message.from_user.first_name
58
-
59
  audio_telegram = (
60
  (message.reply_to_message.audio or message.reply_to_message.voice)
61
- if message.reply_to_message else None
 
 
 
 
 
 
62
  )
63
-
64
  if audio_telegram:
65
  if audio_telegram.file_size > 104857600:
66
  return await mystic.edit_text(_["play_5"])
67
-
68
  duration_min = seconds_to_min(audio_telegram.duration)
69
- if audio_telegram.duration > config.DURATION_LIMIT:
70
  return await mystic.edit_text(
71
  _["play_6"].format(config.DURATION_LIMIT_MIN, app.mention)
72
  )
73
-
74
  file_path = await Telegram.get_filepath(audio=audio_telegram)
75
- downloaded = await Telegram.download(_, message, mystic, file_path)
76
- if downloaded:
77
  message_link = await Telegram.get_link(message)
78
  file_name = await Telegram.get_filename(audio_telegram, audio=True)
79
  dur = await Telegram.get_duration(audio_telegram, file_path)
80
-
81
  details = {
82
  "title": file_name,
83
  "link": message_link,
@@ -98,47 +105,37 @@ async def play_command(client, message: Message, _, chat_id, video, channel, pla
98
  forceplay=fplay,
99
  )
100
  except Exception as e:
101
- err = e if type(e).__name__ == "AssistantErr" else _["general_2"].format(type(e).__name__)
 
 
102
  return await mystic.edit_text(err)
103
-
104
  return await mystic.delete()
105
  return
106
-
107
- video_telegram = (
108
- (message.reply_to_message.video or message.reply_to_message.document)
109
- if message.reply_to_message else None
110
- )
111
-
112
- if video_telegram:
113
  if message.reply_to_message.document:
114
  try:
115
  ext = video_telegram.file_name.split(".")[-1]
116
  if ext.lower() not in formats:
117
  return await mystic.edit_text(
118
- _["play_7"].format(" | ".join(formats))
119
  )
120
  except:
121
  return await mystic.edit_text(
122
- _["play_7"].format(" | ".join(formats))
123
  )
124
-
125
  if video_telegram.file_size > config.TG_VIDEO_FILESIZE_LIMIT:
126
  return await mystic.edit_text(_["play_8"])
127
-
128
  file_path = await Telegram.get_filepath(video=video_telegram)
129
- downloaded = await Telegram.download(_, message, mystic, file_path)
130
- if downloaded:
131
  message_link = await Telegram.get_link(message)
132
  file_name = await Telegram.get_filename(video_telegram)
133
  dur = await Telegram.get_duration(video_telegram, file_path)
134
-
135
  details = {
136
  "title": file_name,
137
  "link": message_link,
138
  "path": file_path,
139
  "dur": dur,
140
  }
141
-
142
  try:
143
  await stream(
144
  _,
@@ -153,136 +150,127 @@ async def play_command(client, message: Message, _, chat_id, video, channel, pla
153
  forceplay=fplay,
154
  )
155
  except Exception as e:
156
- err = e if type(e).__name__ == "AssistantErr" else _["general_2"].format(type(e).__name__)
 
 
157
  return await mystic.edit_text(err)
158
-
159
  return await mystic.delete()
160
  return
161
-
162
- if url:
163
  if await YouTube.exists(url):
164
  if "playlist" in url:
165
  try:
166
- details = await YouTube.playlist(url, config.PLAYLIST_FETCH_LIMIT, user_id)
 
 
 
 
167
  except:
168
  return await mystic.edit_text(_["play_3"])
169
-
170
  plist_type = "yt"
171
- plist_id = (url.split("="))[1].split("&")[0] if "&" in url else (url.split("="))[1]
 
 
 
172
  img = config.PLAYLIST_IMG_URL
173
  cap = _["play_9"]
174
- streamtype = "playlist"
175
-
176
  else:
177
  try:
178
  details, track_id = await YouTube.track(url)
179
  except:
180
  return await mystic.edit_text(_["play_3"])
181
-
182
- img = details["thumb"]
183
- cap = _["play_10"].format(details["title"], details["duration_min"])
184
  streamtype = "youtube"
185
-
 
 
 
 
186
  elif await Spotify.valid(url):
187
  spotify = True
188
- if not config.SPOTIFY_CLIENT_ID or not config.SPOTIFY_CLIENT_SECRET:
189
  return await mystic.edit_text(
190
- sᴘᴏᴛɪғʏ ɪs ɴᴏᴛ sᴜᴘᴘᴏʀᴛᴇᴅ ʏᴇᴛ.\n\nᴘʟᴇᴀsᴇ ᴛʀʏ ᴀɢᴀɪɴ ʟᴀᴛᴇʀ."
191
  )
192
-
193
  if "track" in url:
194
  try:
195
  details, track_id = await Spotify.track(url)
196
  except:
197
  return await mystic.edit_text(_["play_3"])
198
-
199
  img = details["thumb"]
200
  cap = _["play_10"].format(details["title"], details["duration_min"])
201
- streamtype = "youtube"
202
-
203
  elif "playlist" in url:
204
  try:
205
  details, plist_id = await Spotify.playlist(url)
206
- except:
207
  return await mystic.edit_text(_["play_3"])
208
-
209
  plist_type = "spplay"
210
  img = config.SPOTIFY_PLAYLIST_IMG_URL
211
  cap = _["play_11"].format(app.mention, message.from_user.mention)
212
- streamtype = "playlist"
213
-
214
  elif "album" in url:
215
  try:
216
  details, plist_id = await Spotify.album(url)
217
  except:
218
  return await mystic.edit_text(_["play_3"])
219
-
220
  plist_type = "spalbum"
221
  img = config.SPOTIFY_ALBUM_IMG_URL
222
  cap = _["play_11"].format(app.mention, message.from_user.mention)
223
- streamtype = "playlist"
224
-
225
  elif "artist" in url:
226
  try:
227
  details, plist_id = await Spotify.artist(url)
228
  except:
229
  return await mystic.edit_text(_["play_3"])
230
-
231
  plist_type = "spartist"
232
  img = config.SPOTIFY_ARTIST_IMG_URL
233
  cap = _["play_11"].format(message.from_user.first_name)
234
- streamtype = "playlist"
235
-
236
  else:
237
  return await mystic.edit_text(_["play_15"])
238
-
239
  elif await Apple.valid(url):
240
  if "album" in url:
241
  try:
242
  details, track_id = await Apple.track(url)
243
  except:
244
  return await mystic.edit_text(_["play_3"])
245
-
246
  img = details["thumb"]
247
  cap = _["play_10"].format(details["title"], details["duration_min"])
248
- streamtype = "youtube"
249
-
250
  elif "playlist" in url:
251
  spotify = True
252
  try:
253
  details, plist_id = await Apple.playlist(url)
254
  except:
255
  return await mystic.edit_text(_["play_3"])
256
-
257
  plist_type = "apple"
258
- img = url
259
  cap = _["play_12"].format(app.mention, message.from_user.mention)
260
- streamtype = "playlist"
261
-
262
  else:
263
  return await mystic.edit_text(_["play_3"])
264
-
265
  elif await Resso.valid(url):
266
  try:
267
  details, track_id = await Resso.track(url)
268
  except:
269
  return await mystic.edit_text(_["play_3"])
270
-
271
  img = details["thumb"]
272
  cap = _["play_10"].format(details["title"], details["duration_min"])
273
- streamtype = "youtube"
274
-
275
  elif await SoundCloud.valid(url):
276
  try:
277
  details, track_path = await SoundCloud.download(url)
278
  except:
279
  return await mystic.edit_text(_["play_3"])
280
-
281
- if details["duration_sec"] > config.DURATION_LIMIT:
282
  return await mystic.edit_text(
283
- _["play_6"].format(config.DURATION_LIMIT_MIN, app.mention)
 
 
 
284
  )
285
-
286
  try:
287
  await stream(
288
  _,
@@ -296,43 +284,43 @@ async def play_command(client, message: Message, _, chat_id, video, channel, pla
296
  forceplay=fplay,
297
  )
298
  except Exception as e:
299
- err = e if type(e).__name__ == "AssistantErr" else _["general_2"].format(type(e).__name__)
 
 
300
  return await mystic.edit_text(err)
301
-
302
  return await mystic.delete()
303
-
304
  else:
305
  try:
306
- await Drag.stream_call(url)
307
  except NoActiveGroupCall:
308
  await mystic.edit_text(_["black_9"])
309
  return await app.send_message(
310
- chat_id=config.LOGGER_ID,
311
  text=_["play_17"],
312
  )
313
  except Exception as e:
 
314
  return await mystic.edit_text(_["general_2"].format(type(e).__name__))
315
-
316
  await mystic.edit_text(_["str_2"])
317
  try:
318
  await stream(
319
  _,
320
  mystic,
321
- user_id,
322
  url,
323
  chat_id,
324
- user_name,
325
  message.chat.id,
326
  video=video,
327
  streamtype="index",
328
  forceplay=fplay,
329
  )
330
  except Exception as e:
331
- err = e if type(e).__name__ == "AssistantErr" else _["general_2"].format(type(e).__name__)
 
 
332
  return await mystic.edit_text(err)
333
-
334
- return await play_logs(message, streamtype="M3U8 or Index Link")
335
-
336
  else:
337
  if len(message.command) < 2:
338
  buttons = botplaylist_markup(_)
@@ -340,24 +328,20 @@ async def play_command(client, message: Message, _, chat_id, video, channel, pla
340
  _["play_18"],
341
  reply_markup=InlineKeyboardMarkup(buttons),
342
  )
343
-
344
  slider = True
345
  query = message.text.split(None, 1)[1]
346
  if "-v" in query:
347
  query = query.replace("-v", "")
348
-
349
  try:
350
  details, track_id = await YouTube.track(query)
351
  except:
352
  return await mystic.edit_text(_["play_3"])
353
-
354
  streamtype = "youtube"
355
-
356
  if str(playmode) == "Direct":
357
  if not plist_type:
358
- if details.get("duration_min"):
359
  duration_sec = time_to_seconds(details["duration_min"])
360
- if duration_sec and duration_sec > config.DURATION_LIMIT:
361
  return await mystic.edit_text(
362
  _["play_6"].format(config.DURATION_LIMIT_MIN, app.mention)
363
  )
@@ -374,7 +358,6 @@ async def play_command(client, message: Message, _, chat_id, video, channel, pla
374
  _["play_13"],
375
  reply_markup=InlineKeyboardMarkup(buttons),
376
  )
377
-
378
  try:
379
  await stream(
380
  _,
@@ -390,38 +373,39 @@ async def play_command(client, message: Message, _, chat_id, video, channel, pla
390
  forceplay=fplay,
391
  )
392
  except Exception as e:
393
- err = e if type(e).__name__ == "AssistantErr" else _["general_2"].format(type(e).__name__)
 
 
394
  return await mystic.edit_text(err)
395
-
396
  await mystic.delete()
397
  return await play_logs(message, streamtype=streamtype)
398
-
399
  else:
400
  if plist_type:
401
- ran_hash = "".join(random.choices(string.ascii_uppercase + string.digits, k=10))
 
 
402
  lyrical[ran_hash] = plist_id
403
  buttons = playlist_markup(
404
  _,
405
  ran_hash,
406
- user_id,
407
  plist_type,
408
  "c" if channel else "g",
409
  "f" if fplay else "d",
410
  )
411
  await mystic.delete()
412
  await message.reply_photo(
413
- photo=(details["thumb"] if plist_type == "yt" else (details if plist_type == "apple" else img)),
414
  caption=cap,
415
  reply_markup=InlineKeyboardMarkup(buttons),
416
  )
417
  return await play_logs(message, streamtype=f"Playlist : {plist_type}")
418
-
419
  else:
420
  if slider:
421
  buttons = slider_markup(
422
  _,
423
  track_id,
424
- user_id,
425
  query,
426
  0,
427
  "c" if channel else "g",
@@ -436,83 +420,74 @@ async def play_command(client, message: Message, _, chat_id, video, channel, pla
436
  ),
437
  reply_markup=InlineKeyboardMarkup(buttons),
438
  )
439
- return await play_logs(message, streamtype="Searched on YouTube")
440
-
441
  else:
442
  buttons = track_markup(
443
  _,
444
  track_id,
445
- user_id,
446
  "c" if channel else "g",
447
  "f" if fplay else "d",
448
  )
449
  await mystic.delete()
450
  await message.reply_photo(
451
- photo=details["thumb"],
452
- caption=_["play_10"].format(
453
- details["title"],
454
- details["duration_min"],
455
- ),
456
  reply_markup=InlineKeyboardMarkup(buttons),
457
  )
458
- return await play_logs(message, streamtype="URL Search Inline")
 
459
 
460
  @app.on_callback_query(filters.regex("MusicStream") & ~BANNED_USERS)
461
  @languageCB
462
- @capture_callback_err
463
  async def play_music(client, CallbackQuery, _):
464
- try:
465
- callback_data = CallbackQuery.data.split(None, 1)[1]
466
- vidid, user_id, mode, cplay, fplay = callback_data.split("|")
467
-
468
- if CallbackQuery.from_user.id != int(user_id):
469
  return await CallbackQuery.answer(_["playcb_1"], show_alert=True)
470
-
 
 
471
  chat_id, channel = await get_channeplayCB(_, cplay, CallbackQuery)
472
-
473
- user_name = CallbackQuery.from_user.first_name
 
 
474
  await CallbackQuery.message.delete()
475
  await CallbackQuery.answer()
476
-
477
- try:
478
- mystic = await CallbackQuery.message.reply_text(
479
- _["play_2"].format(channel) if channel else random.choice(AYU)
480
- )
481
- except FloodWait as e:
482
- await asyncio.sleep(e.value)
483
- mystic = await CallbackQuery.message.reply_text(
484
- _["play_2"].format(channel) if channel else random.choice(AYU)
485
- )
486
- except RandomIdDuplicate:
487
- mystic = await app.send_message(
488
- CallbackQuery.message.chat.id,
489
- _["play_2"].format(channel) if channel else random.choice(AYU)
490
- )
491
-
492
- details, track_id = await YouTube.track(vidid, videoid=vidid)
493
-
494
- if details.get("duration_min"):
495
- duration_sec = time_to_seconds(details["duration_min"])
496
- if duration_sec and duration_sec > config.DURATION_LIMIT:
497
- return await mystic.edit_text(
498
- _["play_6"].format(config.DURATION_LIMIT_MIN, app.mention)
499
- )
500
- else:
501
- buttons = livestream_markup(
502
- _,
503
- track_id,
504
- CallbackQuery.from_user.id,
505
- mode,
506
- "c" if cplay == "c" else "g",
507
- "f" if fplay else "d",
508
- )
509
  return await mystic.edit_text(
510
- _["play_13"], reply_markup=InlineKeyboardMarkup(buttons)
511
  )
512
-
513
- video = mode == "v"
514
- forceplay = fplay == "f"
515
-
 
 
 
 
 
 
 
 
 
 
 
 
516
  await stream(
517
  _,
518
  mystic,
@@ -523,136 +498,57 @@ async def play_music(client, CallbackQuery, _):
523
  CallbackQuery.message.chat.id,
524
  video,
525
  streamtype="youtube",
526
- forceplay=forceplay,
527
  )
528
-
529
- await mystic.delete()
530
-
531
  except Exception as e:
532
- err = e if type(e).__name__ == "AssistantErr" else _["general_2"].format(type(e).__name__)
533
- return await CallbackQuery.message.reply_text(err)
 
 
 
534
 
535
 
536
  @app.on_callback_query(filters.regex("AnonymousAdmin") & ~BANNED_USERS)
537
- @capture_callback_err
538
  async def anonymous_check(client, CallbackQuery):
539
  try:
540
  await CallbackQuery.answer(
541
- "» ʀᴇᴠᴇʀᴛ ʙᴀᴄᴋ ᴛᴏ ᴜsᴇʀ ᴀᴄᴄᴏᴜɴᴛ :\n\n"
542
- "ᴏᴘᴇɴ ʏᴏᴜʀ ɢʀᴏᴜᴘ sᴇᴛᴛɪɴɢs.\n"
543
- "-> ᴀᴅᴍɪɴɪsᴛʀᴀᴛᴏʀs\n-> ᴄʟɪᴄᴋ ᴏɴ ʏᴏᴜʀ ɴᴀᴍᴇ\n"
544
- "-> ᴜɴᴄʜᴇᴄᴋ ᴀɴᴏɴʏᴍᴏᴜs ᴀᴅᴍɪɴ ᴘᴇʀᴍɪssɪᴏɴs.",
545
  show_alert=True,
546
  )
547
  except:
548
  pass
549
 
550
 
551
- @app.on_callback_query(filters.regex("AnniePlaylists") & ~BANNED_USERS)
552
  @languageCB
553
- @capture_callback_err
554
  async def play_playlists_command(client, CallbackQuery, _):
555
- try:
556
- callback_data = CallbackQuery.data.split(None, 1)[1]
557
- videoid, user_id, ptype, mode, cplay, fplay = callback_data.split("|")
558
-
559
- if CallbackQuery.from_user.id != int(user_id):
560
- return await CallbackQuery.answer(_["playcb_1"], show_alert=True)
561
-
562
- chat_id, channel = await get_channeplayCB(_, cplay, CallbackQuery)
563
- user_name = CallbackQuery.from_user.first_name
564
- await CallbackQuery.message.delete()
565
- await CallbackQuery.answer()
566
-
567
  try:
568
- mystic = await CallbackQuery.message.reply_text(
569
- _["play_2"].format(channel) if channel else random.choice(AYU)
570
- )
571
- except FloodWait as e:
572
- await asyncio.sleep(e.value)
573
- mystic = await CallbackQuery.message.reply_text(
574
- _["play_2"].format(channel) if channel else random.choice(AYU)
575
- )
576
- except RandomIdDuplicate:
577
- mystic = await app.send_message(
578
- CallbackQuery.message.chat.id,
579
- _["play_2"].format(channel) if channel else random.choice(AYU)
580
- )
581
-
582
- videoid = lyrical.get(videoid)
583
- video = mode == "v"
584
- forceplay = fplay == "f"
585
- spotify = True
586
-
587
- if ptype == "yt":
588
- spotify = False
589
- result = await YouTube.playlist(videoid, config.PLAYLIST_FETCH_LIMIT, CallbackQuery.from_user.id, True)
590
- elif ptype == "spplay":
591
- result, _ = await Spotify.playlist(videoid)
592
- elif ptype == "spalbum":
593
- result, _ = await Spotify.album(videoid)
594
- elif ptype == "spartist":
595
- result, _ = await Spotify.artist(videoid)
596
- elif ptype == "apple":
597
- result, _ = await Apple.playlist(videoid, True)
598
- else:
599
  return
600
-
601
- await stream(
602
- _,
603
- mystic,
604
- CallbackQuery.from_user.id,
605
- result,
606
- chat_id,
607
- user_name,
608
- CallbackQuery.message.chat.id,
609
- video,
610
- streamtype="playlist",
611
- spotify=spotify,
612
- forceplay=forceplay,
613
- )
614
-
615
- await mystic.delete()
616
-
617
- except Exception as e:
618
- err = e if type(e).__name__ == "AssistantErr" else _["general_2"].format(type(e).__name__)
619
- return await CallbackQuery.message.reply_text(err)
620
-
621
-
622
- @app.on_callback_query(filters.regex("slider") & ~BANNED_USERS)
623
- @languageCB
624
- @capture_callback_err
625
- async def slider_queries(client, CallbackQuery, _):
626
  try:
627
- callback_data = CallbackQuery.data.split(None, 1)[1]
628
- what, rtype, query, user_id, cplay, fplay = callback_data.split("|")
629
-
630
- if CallbackQuery.from_user.id != int(user_id):
631
- return await CallbackQuery.answer(_["playcb_1"], show_alert=True)
632
-
633
- rtype = int(rtype)
634
- query_type = (rtype + 1) if what == "F" else (rtype - 1)
635
-
636
- if query_type > 9:
637
- query_type = 0
638
- if query_type < 0:
639
- query_type = 9
640
-
641
- title, duration_min, thumbnail, vidid = await YouTube.slider(query, query_type)
642
-
643
- buttons = slider_markup(_, vidid, user_id, query, query_type, cplay, fplay)
644
- med = InputMediaPhoto(
645
- media=thumbnail,
646
- caption=_["play_10"].format(
647
- title.title(),
648
- duration_min,
649
- ),
650
- )
651
-
652
- await CallbackQuery.edit_message_media(
653
- media=med, reply_markup=InlineKeyboardMarkup(buttons)
654
- )
655
- await CallbackQuery.answer(_["playcb_2"])
656
-
657
- except Exception:
658
- pass
 
1
  import random
2
  import string
 
3
 
4
  from pyrogram import filters
 
5
  from pyrogram.types import InlineKeyboardMarkup, InputMediaPhoto, Message
6
  from pytgcalls.exceptions import NoActiveGroupCall
7
 
8
  import config
9
+ from AnonXMusic import Apple, Resso, SoundCloud, Spotify, Telegram, YouTube, app
10
+ from AnonXMusic.core.call import Anony
11
+ from AnonXMusic.utils import seconds_to_min, time_to_seconds
12
+ from AnonXMusic.utils.channelplay import get_channeplayCB
13
+ from AnonXMusic.utils.decorators.language import languageCB
14
+ from AnonXMusic.utils.decorators.play import PlayWrapper
15
+ from AnonXMusic.utils.formatters import formats
16
+ from AnonXMusic.utils.inline import (
 
 
17
  botplaylist_markup,
18
  livestream_markup,
19
  playlist_markup,
20
  slider_markup,
21
  track_markup,
22
  )
23
+ from AnonXMusic.utils.logger import play_logs
24
+ from AnonXMusic.utils.stream.stream import stream
25
+ from config import BANNED_USERS, lyrical
26
 
27
 
28
  @app.on_message(
29
+ filters.command(
30
+ [
31
+ "play",
32
+ "vplay",
33
+ "cplay",
34
+ "cvplay",
35
+ "playforce",
36
+ "vplayforce",
37
+ "cplayforce",
38
+ "cvplayforce",
39
+ ]
40
+ )
41
+ & filters.group
42
+ & ~BANNED_USERS
43
  )
44
  @PlayWrapper
45
+ async def play_commnd(
46
+ client,
47
+ message: Message,
48
+ _,
49
+ chat_id,
50
+ video,
51
+ channel,
52
+ playmode,
53
+ url,
54
+ fplay,
55
+ ):
56
+ mystic = await message.reply_text(
57
+ _["play_2"].format(channel) if channel else _["play_1"]
58
+ )
59
+ plist_id = None
60
+ slider = None
61
+ plist_type = None
62
+ spotify = None
63
  user_id = message.from_user.id
64
  user_name = message.from_user.first_name
 
65
  audio_telegram = (
66
  (message.reply_to_message.audio or message.reply_to_message.voice)
67
+ if message.reply_to_message
68
+ else None
69
+ )
70
+ video_telegram = (
71
+ (message.reply_to_message.video or message.reply_to_message.document)
72
+ if message.reply_to_message
73
+ else None
74
  )
 
75
  if audio_telegram:
76
  if audio_telegram.file_size > 104857600:
77
  return await mystic.edit_text(_["play_5"])
 
78
  duration_min = seconds_to_min(audio_telegram.duration)
79
+ if (audio_telegram.duration) > config.DURATION_LIMIT:
80
  return await mystic.edit_text(
81
  _["play_6"].format(config.DURATION_LIMIT_MIN, app.mention)
82
  )
 
83
  file_path = await Telegram.get_filepath(audio=audio_telegram)
84
+ if await Telegram.download(_, message, mystic, file_path):
 
85
  message_link = await Telegram.get_link(message)
86
  file_name = await Telegram.get_filename(audio_telegram, audio=True)
87
  dur = await Telegram.get_duration(audio_telegram, file_path)
 
88
  details = {
89
  "title": file_name,
90
  "link": message_link,
 
105
  forceplay=fplay,
106
  )
107
  except Exception as e:
108
+ print(f"Error: {e}")
109
+ ex_type = type(e).__name__
110
+ err = e if ex_type == "AssistantErr" else _["general_2"].format(ex_type)
111
  return await mystic.edit_text(err)
 
112
  return await mystic.delete()
113
  return
114
+ elif video_telegram:
 
 
 
 
 
 
115
  if message.reply_to_message.document:
116
  try:
117
  ext = video_telegram.file_name.split(".")[-1]
118
  if ext.lower() not in formats:
119
  return await mystic.edit_text(
120
+ _["play_7"].format(f"{' | '.join(formats)}")
121
  )
122
  except:
123
  return await mystic.edit_text(
124
+ _["play_7"].format(f"{' | '.join(formats)}")
125
  )
 
126
  if video_telegram.file_size > config.TG_VIDEO_FILESIZE_LIMIT:
127
  return await mystic.edit_text(_["play_8"])
 
128
  file_path = await Telegram.get_filepath(video=video_telegram)
129
+ if await Telegram.download(_, message, mystic, file_path):
 
130
  message_link = await Telegram.get_link(message)
131
  file_name = await Telegram.get_filename(video_telegram)
132
  dur = await Telegram.get_duration(video_telegram, file_path)
 
133
  details = {
134
  "title": file_name,
135
  "link": message_link,
136
  "path": file_path,
137
  "dur": dur,
138
  }
 
139
  try:
140
  await stream(
141
  _,
 
150
  forceplay=fplay,
151
  )
152
  except Exception as e:
153
+ print(f"Error: {e}")
154
+ ex_type = type(e).__name__
155
+ err = e if ex_type == "AssistantErr" else _["general_2"].format(ex_type)
156
  return await mystic.edit_text(err)
 
157
  return await mystic.delete()
158
  return
159
+ elif url:
 
160
  if await YouTube.exists(url):
161
  if "playlist" in url:
162
  try:
163
+ details = await YouTube.playlist(
164
+ url,
165
+ config.PLAYLIST_FETCH_LIMIT,
166
+ message.from_user.id,
167
+ )
168
  except:
169
  return await mystic.edit_text(_["play_3"])
170
+ streamtype = "playlist"
171
  plist_type = "yt"
172
+ if "&" in url:
173
+ plist_id = (url.split("=")[1]).split("&")[0]
174
+ else:
175
+ plist_id = url.split("=")[1]
176
  img = config.PLAYLIST_IMG_URL
177
  cap = _["play_9"]
 
 
178
  else:
179
  try:
180
  details, track_id = await YouTube.track(url)
181
  except:
182
  return await mystic.edit_text(_["play_3"])
 
 
 
183
  streamtype = "youtube"
184
+ img = details["thumb"]
185
+ cap = _["play_10"].format(
186
+ details["title"],
187
+ details["duration_min"],
188
+ )
189
  elif await Spotify.valid(url):
190
  spotify = True
191
+ if not config.SPOTIFY_CLIENT_ID and not config.SPOTIFY_CLIENT_SECRET:
192
  return await mystic.edit_text(
193
+ sᴘᴏᴛɪғʏ ɪs ɴᴏᴛ sᴜᴘᴘᴏʀᴛᴇᴅ ʏᴇᴛ.\n\nᴘʟᴇᴀsᴇ ᴛʀʏ ᴀɢᴀɪɴ ʟᴀᴛᴇʀ."
194
  )
 
195
  if "track" in url:
196
  try:
197
  details, track_id = await Spotify.track(url)
198
  except:
199
  return await mystic.edit_text(_["play_3"])
200
+ streamtype = "youtube"
201
  img = details["thumb"]
202
  cap = _["play_10"].format(details["title"], details["duration_min"])
 
 
203
  elif "playlist" in url:
204
  try:
205
  details, plist_id = await Spotify.playlist(url)
206
+ except Exception:
207
  return await mystic.edit_text(_["play_3"])
208
+ streamtype = "playlist"
209
  plist_type = "spplay"
210
  img = config.SPOTIFY_PLAYLIST_IMG_URL
211
  cap = _["play_11"].format(app.mention, message.from_user.mention)
 
 
212
  elif "album" in url:
213
  try:
214
  details, plist_id = await Spotify.album(url)
215
  except:
216
  return await mystic.edit_text(_["play_3"])
217
+ streamtype = "playlist"
218
  plist_type = "spalbum"
219
  img = config.SPOTIFY_ALBUM_IMG_URL
220
  cap = _["play_11"].format(app.mention, message.from_user.mention)
 
 
221
  elif "artist" in url:
222
  try:
223
  details, plist_id = await Spotify.artist(url)
224
  except:
225
  return await mystic.edit_text(_["play_3"])
226
+ streamtype = "playlist"
227
  plist_type = "spartist"
228
  img = config.SPOTIFY_ARTIST_IMG_URL
229
  cap = _["play_11"].format(message.from_user.first_name)
 
 
230
  else:
231
  return await mystic.edit_text(_["play_15"])
 
232
  elif await Apple.valid(url):
233
  if "album" in url:
234
  try:
235
  details, track_id = await Apple.track(url)
236
  except:
237
  return await mystic.edit_text(_["play_3"])
238
+ streamtype = "youtube"
239
  img = details["thumb"]
240
  cap = _["play_10"].format(details["title"], details["duration_min"])
 
 
241
  elif "playlist" in url:
242
  spotify = True
243
  try:
244
  details, plist_id = await Apple.playlist(url)
245
  except:
246
  return await mystic.edit_text(_["play_3"])
247
+ streamtype = "playlist"
248
  plist_type = "apple"
 
249
  cap = _["play_12"].format(app.mention, message.from_user.mention)
250
+ img = url
 
251
  else:
252
  return await mystic.edit_text(_["play_3"])
 
253
  elif await Resso.valid(url):
254
  try:
255
  details, track_id = await Resso.track(url)
256
  except:
257
  return await mystic.edit_text(_["play_3"])
258
+ streamtype = "youtube"
259
  img = details["thumb"]
260
  cap = _["play_10"].format(details["title"], details["duration_min"])
 
 
261
  elif await SoundCloud.valid(url):
262
  try:
263
  details, track_path = await SoundCloud.download(url)
264
  except:
265
  return await mystic.edit_text(_["play_3"])
266
+ duration_sec = details["duration_sec"]
267
+ if duration_sec > config.DURATION_LIMIT:
268
  return await mystic.edit_text(
269
+ _["play_6"].format(
270
+ config.DURATION_LIMIT_MIN,
271
+ app.mention,
272
+ )
273
  )
 
274
  try:
275
  await stream(
276
  _,
 
284
  forceplay=fplay,
285
  )
286
  except Exception as e:
287
+ print(f"Error: {e}")
288
+ ex_type = type(e).__name__
289
+ err = e if ex_type == "AssistantErr" else _["general_2"].format(ex_type)
290
  return await mystic.edit_text(err)
 
291
  return await mystic.delete()
 
292
  else:
293
  try:
294
+ await Aviax.stream_call(url)
295
  except NoActiveGroupCall:
296
  await mystic.edit_text(_["black_9"])
297
  return await app.send_message(
298
+ chat_id=config.LOG_GROUP_ID,
299
  text=_["play_17"],
300
  )
301
  except Exception as e:
302
+ print(f"Error: {e}")
303
  return await mystic.edit_text(_["general_2"].format(type(e).__name__))
 
304
  await mystic.edit_text(_["str_2"])
305
  try:
306
  await stream(
307
  _,
308
  mystic,
309
+ message.from_user.id,
310
  url,
311
  chat_id,
312
+ message.from_user.first_name,
313
  message.chat.id,
314
  video=video,
315
  streamtype="index",
316
  forceplay=fplay,
317
  )
318
  except Exception as e:
319
+ print(f"Error: {e}")
320
+ ex_type = type(e).__name__
321
+ err = e if ex_type == "AssistantErr" else _["general_2"].format(ex_type)
322
  return await mystic.edit_text(err)
323
+ return await play_logs(message, streamtype="M3u8 or Index Link")
 
 
324
  else:
325
  if len(message.command) < 2:
326
  buttons = botplaylist_markup(_)
 
328
  _["play_18"],
329
  reply_markup=InlineKeyboardMarkup(buttons),
330
  )
 
331
  slider = True
332
  query = message.text.split(None, 1)[1]
333
  if "-v" in query:
334
  query = query.replace("-v", "")
 
335
  try:
336
  details, track_id = await YouTube.track(query)
337
  except:
338
  return await mystic.edit_text(_["play_3"])
 
339
  streamtype = "youtube"
 
340
  if str(playmode) == "Direct":
341
  if not plist_type:
342
+ if details["duration_min"]:
343
  duration_sec = time_to_seconds(details["duration_min"])
344
+ if duration_sec > config.DURATION_LIMIT:
345
  return await mystic.edit_text(
346
  _["play_6"].format(config.DURATION_LIMIT_MIN, app.mention)
347
  )
 
358
  _["play_13"],
359
  reply_markup=InlineKeyboardMarkup(buttons),
360
  )
 
361
  try:
362
  await stream(
363
  _,
 
373
  forceplay=fplay,
374
  )
375
  except Exception as e:
376
+ print(f"Error: {e}")
377
+ ex_type = type(e).__name__
378
+ err = e if ex_type == "AssistantErr" else _["general_2"].format(ex_type)
379
  return await mystic.edit_text(err)
 
380
  await mystic.delete()
381
  return await play_logs(message, streamtype=streamtype)
 
382
  else:
383
  if plist_type:
384
+ ran_hash = "".join(
385
+ random.choices(string.ascii_uppercase + string.digits, k=10)
386
+ )
387
  lyrical[ran_hash] = plist_id
388
  buttons = playlist_markup(
389
  _,
390
  ran_hash,
391
+ message.from_user.id,
392
  plist_type,
393
  "c" if channel else "g",
394
  "f" if fplay else "d",
395
  )
396
  await mystic.delete()
397
  await message.reply_photo(
398
+ photo=img,
399
  caption=cap,
400
  reply_markup=InlineKeyboardMarkup(buttons),
401
  )
402
  return await play_logs(message, streamtype=f"Playlist : {plist_type}")
 
403
  else:
404
  if slider:
405
  buttons = slider_markup(
406
  _,
407
  track_id,
408
+ message.from_user.id,
409
  query,
410
  0,
411
  "c" if channel else "g",
 
420
  ),
421
  reply_markup=InlineKeyboardMarkup(buttons),
422
  )
423
+ return await play_logs(message, streamtype=f"Searched on Youtube")
 
424
  else:
425
  buttons = track_markup(
426
  _,
427
  track_id,
428
+ message.from_user.id,
429
  "c" if channel else "g",
430
  "f" if fplay else "d",
431
  )
432
  await mystic.delete()
433
  await message.reply_photo(
434
+ photo=img,
435
+ caption=cap,
 
 
 
436
  reply_markup=InlineKeyboardMarkup(buttons),
437
  )
438
+ return await play_logs(message, streamtype=f"URL Searched Inline")
439
+
440
 
441
  @app.on_callback_query(filters.regex("MusicStream") & ~BANNED_USERS)
442
  @languageCB
 
443
  async def play_music(client, CallbackQuery, _):
444
+ callback_data = CallbackQuery.data.strip()
445
+ callback_request = callback_data.split(None, 1)[1]
446
+ vidid, user_id, mode, cplay, fplay = callback_request.split("|")
447
+ if CallbackQuery.from_user.id != int(user_id):
448
+ try:
449
  return await CallbackQuery.answer(_["playcb_1"], show_alert=True)
450
+ except:
451
+ return
452
+ try:
453
  chat_id, channel = await get_channeplayCB(_, cplay, CallbackQuery)
454
+ except:
455
+ return
456
+ user_name = CallbackQuery.from_user.first_name
457
+ try:
458
  await CallbackQuery.message.delete()
459
  await CallbackQuery.answer()
460
+ except:
461
+ pass
462
+ mystic = await CallbackQuery.message.reply_text(
463
+ _["play_2"].format(channel) if channel else _["play_1"]
464
+ )
465
+ try:
466
+ details, track_id = await YouTube.track(vidid, True)
467
+ except:
468
+ return await mystic.edit_text(_["play_3"])
469
+ if details["duration_min"]:
470
+ duration_sec = time_to_seconds(details["duration_min"])
471
+ if duration_sec > config.DURATION_LIMIT:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472
  return await mystic.edit_text(
473
+ _["play_6"].format(config.DURATION_LIMIT_MIN, app.mention)
474
  )
475
+ else:
476
+ buttons = livestream_markup(
477
+ _,
478
+ track_id,
479
+ CallbackQuery.from_user.id,
480
+ mode,
481
+ "c" if cplay == "c" else "g",
482
+ "f" if fplay else "d",
483
+ )
484
+ return await mystic.edit_text(
485
+ _["play_13"],
486
+ reply_markup=InlineKeyboardMarkup(buttons),
487
+ )
488
+ video = True if mode == "v" else None
489
+ ffplay = True if fplay == "f" else None
490
+ try:
491
  await stream(
492
  _,
493
  mystic,
 
498
  CallbackQuery.message.chat.id,
499
  video,
500
  streamtype="youtube",
501
+ forceplay=ffplay,
502
  )
 
 
 
503
  except Exception as e:
504
+ print(f"Error: {e}")
505
+ ex_type = type(e).__name__
506
+ err = e if ex_type == "AssistantErr" else _["general_2"].format(ex_type)
507
+ return await mystic.edit_text(err)
508
+ return await mystic.delete()
509
 
510
 
511
  @app.on_callback_query(filters.regex("AnonymousAdmin") & ~BANNED_USERS)
 
512
  async def anonymous_check(client, CallbackQuery):
513
  try:
514
  await CallbackQuery.answer(
515
+ "» ʀᴇᴠᴇʀᴛ ʙᴀᴄᴋ ᴛᴏ ᴜsᴇʀ ᴀᴄᴄᴏᴜɴᴛ :\n\nᴏᴘᴇɴ ʏᴏᴜʀ ɢʀᴏᴜ�� sᴇᴛᴛɪɴɢs.\n-> ᴀᴅᴍɪɴɪsᴛʀᴀᴛᴏʀs\n-> ᴄʟɪᴄᴋ ᴏɴ ʏᴏᴜʀ ɴᴀᴍᴇ\n-> ᴜɴᴄʜᴇᴄᴋ ᴀɴᴏɴʏᴍᴏᴜs ᴀᴅᴍɪɴ ᴘᴇʀᴍɪssɪᴏɴs.",
 
 
 
516
  show_alert=True,
517
  )
518
  except:
519
  pass
520
 
521
 
522
+ @app.on_callback_query(filters.regex("AviaxPlaylists") & ~BANNED_USERS)
523
  @languageCB
 
524
  async def play_playlists_command(client, CallbackQuery, _):
525
+ callback_data = CallbackQuery.data.strip()
526
+ callback_request = callback_data.split(None, 1)[1]
527
+ (
528
+ videoid,
529
+ user_id,
530
+ ptype,
531
+ mode,
532
+ cplay,
533
+ fplay,
534
+ ) = callback_request.split("|")
535
+ if CallbackQuery.from_user.id != int(user_id):
 
536
  try:
537
+ return await CallbackQuery.answer(_["playcb_1"], show_alert=True)
538
+ except:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  return
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
540
  try:
541
+ chat_id, channel = await get_channeplayCB(_, cplay, CallbackQuery)
542
+ except:
543
+ return
544
+ user_name = CallbackQuery.from_user.first_name
545
+ await CallbackQuery.message.delete()
546
+ try:
547
+ await CallbackQuery.answer()
548
+ except:
549
+ pass
550
+ mystic = await CallbackQuery.message.reply_text(
551
+ _["play_2"].format(channel) if channel else _["play_1"]
552
+ )
553
+ videoid = lyrical.get(videoid)
554
+ video = Tr
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
DragMusic/utils/downloader.py DELETED
@@ -1,201 +0,0 @@
1
- import asyncio
2
- import aiohttp
3
- import aiofiles
4
- import os
5
- import re
6
- from typing import Optional, Union, Dict
7
- from yt_dlp import YoutubeDL
8
- from config import API_URL, API_KEY
9
-
10
- USE_API = bool(API_URL and API_KEY)
11
- _logged_api_skip = False
12
- CHUNK_SIZE = 8192
13
- RETRY_DELAY = 2
14
- cookies_file = "cookies.txt"
15
- download_folder = "/tmp/downloads"
16
- os.makedirs(download_folder, exist_ok=True)
17
-
18
-
19
- def extract_video_id(link: str) -> str:
20
- if "v=" in link:
21
- return link.split("v=")[-1].split("&")[0]
22
- return link.split("/")[-1].split("?")[0]
23
-
24
-
25
- def safe_filename(name: str) -> str:
26
- return re.sub(r"[\\/*?\"<>|]", "_", name).strip()[:100]
27
-
28
-
29
- def file_exists(video_id: str) -> Optional[str]:
30
- for ext in ["mp3", "m4a", "webm"]:
31
- path = f"{download_folder}/{video_id}.{ext}"
32
- if os.path.exists(path):
33
- print(f"[CACHED] Using existing file: {path}")
34
- return path
35
- return None
36
-
37
-
38
- async def api_download_song(link: str) -> Optional[str]:
39
- global _logged_api_skip
40
-
41
- if not USE_API:
42
- if not _logged_api_skip:
43
- print("[SKIPPED] API config missing — using yt-dlp only.")
44
- _logged_api_skip = True
45
- return None
46
-
47
- video_id = extract_video_id(link)
48
- song_url = f"{API_URL}/song/{video_id}?api={API_KEY}"
49
-
50
- try:
51
- async with aiohttp.ClientSession() as session:
52
- while True:
53
- async with session.get(song_url) as response:
54
- if response.status != 200:
55
- print(f"[API ERROR] Status {response.status}")
56
- return None
57
-
58
- data = await response.json()
59
- status = data.get("status", "").lower()
60
-
61
- if status == "downloading":
62
- await asyncio.sleep(RETRY_DELAY)
63
- continue
64
- elif status == "error":
65
- print(f"[API ERROR] Status=error for {video_id}")
66
- return None
67
- elif status == "done":
68
- download_url = data.get("link")
69
- break
70
- else:
71
- print(f"[API ERROR] Unknown status: {status}")
72
- return None
73
-
74
- fmt = data.get("format", "mp3").lower()
75
- path = f"{download_folder}/{video_id}.{fmt}"
76
-
77
- async with session.get(download_url) as file_response:
78
- async with aiofiles.open(path, "wb") as f:
79
- while True:
80
- chunk = await file_response.content.read(CHUNK_SIZE)
81
- if not chunk:
82
- break
83
- await f.write(chunk)
84
-
85
- return path
86
- except Exception as e:
87
- print(f"[API Download Error] {e}")
88
- return None
89
-
90
-
91
- def _download_ytdlp(link: str, opts: Dict) -> Optional[str]:
92
- try:
93
- with YoutubeDL(opts) as ydl:
94
- info = ydl.extract_info(link, download=False)
95
- ext = info.get("ext", "webm")
96
- vid = info.get("id")
97
- path = f"{download_folder}/{vid}.{ext}"
98
- if os.path.exists(path):
99
- return path
100
- ydl.download([link])
101
- return path
102
- except Exception as e:
103
- print(f"[yt-dlp Error] {e}")
104
- return None
105
-
106
-
107
- async def yt_dlp_download(link: str, type: str, format_id: str = None, title: str = None) -> Optional[str]:
108
- loop = asyncio.get_running_loop()
109
-
110
- if type == "audio":
111
- opts = {
112
- "format": "bestaudio/best",
113
- "outtmpl": f"{download_folder}/%(id)s.%(ext)s",
114
- "quiet": True,
115
- "no_warnings": True,
116
- "cookiefile": cookies_file,
117
- "noplaylist": True,
118
- "concurrent_fragment_downloads": 5,
119
- }
120
- return await loop.run_in_executor(None, _download_ytdlp, link, opts)
121
-
122
- elif type == "video":
123
- opts = {
124
- "format": "best[height<=?720][width<=?1280]",
125
- "outtmpl": f"{download_folder}/%(id)s.%(ext)s",
126
- "quiet": True,
127
- "no_warnings": True,
128
- "cookiefile": cookies_file,
129
- "noplaylist": True,
130
- "concurrent_fragment_downloads": 5,
131
- }
132
- return await loop.run_in_executor(None, _download_ytdlp, link, opts)
133
-
134
- elif type == "song_video" and format_id and title:
135
- safe_title = safe_filename(title)
136
- opts = {
137
- "format": f"{format_id}+140",
138
- "outtmpl": f"{download_folder}/{safe_title}.mp4",
139
- "quiet": True,
140
- "no_warnings": True,
141
- "prefer_ffmpeg": True,
142
- "merge_output_format": "mp4",
143
- "cookiefile": cookies_file,
144
- }
145
- await loop.run_in_executor(None, lambda: YoutubeDL(opts).download([link]))
146
- return f"{download_folder}/{safe_title}.mp4"
147
-
148
- elif type == "song_audio" and format_id and title:
149
- safe_title = safe_filename(title)
150
- opts = {
151
- "format": format_id,
152
- "outtmpl": f"{download_folder}/{safe_title}.%(ext)s",
153
- "quiet": True,
154
- "no_warnings": True,
155
- "prefer_ffmpeg": True,
156
- "cookiefile": cookies_file,
157
- "postprocessors": [{
158
- "key": "FFmpegExtractAudio",
159
- "preferredcodec": "mp3",
160
- "preferredquality": "192",
161
- }],
162
- }
163
- await loop.run_in_executor(None, lambda: YoutubeDL(opts).download([link]))
164
- return f"{download_folder}/{safe_title}.mp3"
165
-
166
- return None
167
-
168
-
169
- async def download_audio_concurrent(link: str) -> Optional[str]:
170
- video_id = extract_video_id(link)
171
-
172
- existing = file_exists(video_id)
173
- if existing:
174
- return existing
175
-
176
- if not USE_API:
177
- return await yt_dlp_download(link, type="audio")
178
-
179
- yt_task = asyncio.create_task(yt_dlp_download(link, type="audio"))
180
- api_task = asyncio.create_task(api_download_song(link))
181
-
182
- done, _ = await asyncio.wait([yt_task, api_task], return_when=asyncio.FIRST_COMPLETED)
183
-
184
- for task in done:
185
- try:
186
- result = task.result()
187
- if result:
188
- return result
189
- except Exception as e:
190
- print(f"[Download Task Error] {e}")
191
-
192
- for task in [yt_task, api_task]:
193
- if not task.done():
194
- try:
195
- result = await task
196
- if result:
197
- return result
198
- except Exception as e:
199
- print(f"[Fallback Task Error] {e}")
200
-
201
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
DragMusic/utils/stream/stream.py CHANGED
@@ -75,7 +75,7 @@ async def stream(
75
  status = True if video else None
76
  try:
77
  file_path, direct = await YouTube.download(
78
- vidid, mystic, video=status
79
  )
80
  except:
81
  raise AssistantErr(_["play_14"])
@@ -139,7 +139,7 @@ async def stream(
139
  status = True if video else None
140
  try:
141
  file_path, direct = await YouTube.download(
142
- vidid, mystic, video=status
143
  )
144
  except:
145
  raise AssistantErr(_["play_14"])
@@ -417,4 +417,4 @@ async def stream(
417
  )
418
  db[chat_id][0]["mystic"] = run
419
  db[chat_id][0]["markup"] = "tg"
420
- await mystic.delete()
 
75
  status = True if video else None
76
  try:
77
  file_path, direct = await YouTube.download(
78
+ vidid, mystic, video=status, videoid=True
79
  )
80
  except:
81
  raise AssistantErr(_["play_14"])
 
139
  status = True if video else None
140
  try:
141
  file_path, direct = await YouTube.download(
142
+ vidid, mystic, videoid=True, video=status
143
  )
144
  except:
145
  raise AssistantErr(_["play_14"])
 
417
  )
418
  db[chat_id][0]["mystic"] = run
419
  db[chat_id][0]["markup"] = "tg"
420
+ await mystic.delete()
config.py CHANGED
@@ -117,14 +117,3 @@ if SUPPORT_CHAT:
117
  raise SystemExit(
118
  "[ERROR] - Your SUPPORT_CHAT url is wrong. Please ensure that it starts with https://"
119
  )
120
-
121
- # Miscellaneous
122
- REPLY_MESSAGE = getenv("REPLY_MESSAGE", None)
123
- F_SUB_URL = getenv("F_SUB_URL", None)
124
- WELCOME_DELAY_KICK_SEC = getenv("WELCOME_DELAY_KICK_SEC", None)
125
-
126
- # Add these new variables
127
- AYU = [
128
- "❤️", "✨", "🔥", "🎵", "🎶",
129
- "🎉", "😊", "👍", "🚀", "🌟"
130
- ]
 
117
  raise SystemExit(
118
  "[ERROR] - Your SUPPORT_CHAT url is wrong. Please ensure that it starts with https://"
119
  )
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -35,7 +35,7 @@ googlesearch-python
35
  unidecode
36
  #git+https://github.com/joetats/youtube_search@master
37
  #git+https://github.com/alexmercerind/youtube-search-python@main
38
- https://github.com/KurimuzonAkuma/pyrogram/archive/v2.1.23.zip
39
  git+https://github.com/AsmSafone/SafoneAPI
40
  bing_image_downloader
41
  openai==0.28
 
35
  unidecode
36
  #git+https://github.com/joetats/youtube_search@master
37
  #git+https://github.com/alexmercerind/youtube-search-python@main
38
+ https://github.com/KurimuzonAkuma/pyrogram/archive/v2.2.6.zip
39
  git+https://github.com/AsmSafone/SafoneAPI
40
  bing_image_downloader
41
  openai==0.28