media-downloader 0.11.22__py2.py3-none-any.whl → 0.11.24__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of media-downloader might be problematic. Click here for more details.
- media_downloader/media_downloader.py +38 -39
- media_downloader/media_downloader_mcp.py +10 -4
- media_downloader/version.py +1 -1
- {media_downloader-0.11.22.dist-info → media_downloader-0.11.24.dist-info}/METADATA +3 -8
- media_downloader-0.11.24.dist-info/RECORD +11 -0
- media_downloader-0.11.22.dist-info/RECORD +0 -11
- {media_downloader-0.11.22.dist-info → media_downloader-0.11.24.dist-info}/LICENSE +0 -0
- {media_downloader-0.11.22.dist-info → media_downloader-0.11.24.dist-info}/WHEEL +0 -0
- {media_downloader-0.11.22.dist-info → media_downloader-0.11.24.dist-info}/entry_points.txt +0 -0
- {media_downloader-0.11.22.dist-info → media_downloader-0.11.24.dist-info}/top_level.txt +0 -0
|
@@ -5,7 +5,6 @@ import os
|
|
|
5
5
|
import sys
|
|
6
6
|
import re
|
|
7
7
|
import getopt
|
|
8
|
-
from typing import List
|
|
9
8
|
import logging
|
|
10
9
|
import requests
|
|
11
10
|
import yt_dlp
|
|
@@ -52,8 +51,8 @@ class YtDlpLogger:
|
|
|
52
51
|
|
|
53
52
|
class MediaDownloader:
|
|
54
53
|
def __init__(
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
self, links: list = [], download_directory: str = None, audio: bool = False
|
|
55
|
+
):
|
|
57
56
|
self.links = links
|
|
58
57
|
if download_directory:
|
|
59
58
|
self.download_directory = download_directory
|
|
@@ -115,18 +114,43 @@ class MediaDownloader:
|
|
|
115
114
|
return None
|
|
116
115
|
|
|
117
116
|
def get_channel_videos(self, channel, limit=-1):
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
self.logger.debug(f"Fetching videos for channel: {channel}, limit: {limit}")
|
|
118
|
+
username = channel
|
|
119
|
+
attempts = 0
|
|
120
|
+
while attempts < 3:
|
|
121
|
+
url = f"https://www.youtube.com/user/{username}/videos"
|
|
122
|
+
self.logger.debug(f"Trying URL: {url}")
|
|
123
|
+
page = requests.get(url).content
|
|
124
|
+
data = str(page).split(" ")
|
|
125
|
+
item = 'href="/watch?'
|
|
126
|
+
vids = [
|
|
127
|
+
line.replace('href="', "youtube.com") for line in data if item in line
|
|
128
|
+
]
|
|
129
|
+
if vids:
|
|
130
|
+
self.logger.debug(f"Found {len(vids)} videos")
|
|
131
|
+
x = 0
|
|
132
|
+
for vid in vids:
|
|
133
|
+
if limit < 0 or x < limit:
|
|
134
|
+
self.append_link(vid)
|
|
135
|
+
x += 1
|
|
136
|
+
return
|
|
137
|
+
else:
|
|
138
|
+
url = f"https://www.youtube.com/c/{channel}/videos"
|
|
123
139
|
self.logger.debug(f"Trying URL: {url}")
|
|
124
140
|
page = requests.get(url).content
|
|
125
141
|
data = str(page).split(" ")
|
|
126
|
-
item =
|
|
127
|
-
vids = [
|
|
128
|
-
|
|
129
|
-
|
|
142
|
+
item = "https://i.ytimg.com/vi/"
|
|
143
|
+
vids = []
|
|
144
|
+
for line in data:
|
|
145
|
+
if item in line:
|
|
146
|
+
try:
|
|
147
|
+
found = re.search(
|
|
148
|
+
"https://i.ytimg.com/vi/(.+?)/hqdefault.", line
|
|
149
|
+
).group(1)
|
|
150
|
+
vid = f"https://www.youtube.com/watch?v={found}"
|
|
151
|
+
vids.append(vid)
|
|
152
|
+
except AttributeError:
|
|
153
|
+
continue
|
|
130
154
|
if vids:
|
|
131
155
|
self.logger.debug(f"Found {len(vids)} videos")
|
|
132
156
|
x = 0
|
|
@@ -135,33 +159,8 @@ class MediaDownloader:
|
|
|
135
159
|
self.append_link(vid)
|
|
136
160
|
x += 1
|
|
137
161
|
return
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
self.logger.debug(f"Trying URL: {url}")
|
|
141
|
-
page = requests.get(url).content
|
|
142
|
-
data = str(page).split(" ")
|
|
143
|
-
item = "https://i.ytimg.com/vi/"
|
|
144
|
-
vids = []
|
|
145
|
-
for line in data:
|
|
146
|
-
if item in line:
|
|
147
|
-
try:
|
|
148
|
-
found = re.search(
|
|
149
|
-
"https://i.ytimg.com/vi/(.+?)/hqdefault.", line
|
|
150
|
-
).group(1)
|
|
151
|
-
vid = f"https://www.youtube.com/watch?v={found}"
|
|
152
|
-
vids.append(vid)
|
|
153
|
-
except AttributeError:
|
|
154
|
-
continue
|
|
155
|
-
if vids:
|
|
156
|
-
self.logger.debug(f"Found {len(vids)} videos")
|
|
157
|
-
x = 0
|
|
158
|
-
for vid in vids:
|
|
159
|
-
if limit < 0 or x < limit:
|
|
160
|
-
self.append_link(vid)
|
|
161
|
-
x += 1
|
|
162
|
-
return
|
|
163
|
-
attempts += 1
|
|
164
|
-
self.logger.error(f"Could not find user or channel: {channel}")
|
|
162
|
+
attempts += 1
|
|
163
|
+
self.logger.error(f"Could not find user or channel: {channel}")
|
|
165
164
|
|
|
166
165
|
def progress_hook(self, d):
|
|
167
166
|
if self.progress_callback and d["status"] == "downloading":
|
|
@@ -16,24 +16,30 @@ mcp = FastMCP(name="MediaDownloaderServer")
|
|
|
16
16
|
|
|
17
17
|
@mcp.tool()
|
|
18
18
|
async def download_media(
|
|
19
|
-
video_url: str,
|
|
19
|
+
video_url: str,
|
|
20
|
+
download_directory: Optional[str] = None,
|
|
21
|
+
audio_only: Optional[bool] = False,
|
|
22
|
+
ctx: Context = None,
|
|
20
23
|
) -> str:
|
|
21
24
|
"""Downloads media from a given URL to the specified directory.
|
|
22
25
|
|
|
23
26
|
Args:
|
|
24
27
|
video_url (str): The URL of the media to download.
|
|
25
|
-
download_directory (str): The directory where the media will be saved.
|
|
28
|
+
download_directory (Optional[str]): The directory where the media will be saved. If None, uses default directory.
|
|
26
29
|
audio_only (bool): If True, downloads only the audio. Defaults to False.
|
|
30
|
+
ctx (Context, optional): MCP context for progress reporting.
|
|
27
31
|
|
|
28
32
|
Returns:
|
|
29
33
|
str: The path to the downloaded media file.
|
|
30
34
|
|
|
31
35
|
Raises:
|
|
32
|
-
ValueError: If the URL
|
|
36
|
+
ValueError: If the URL is invalid.
|
|
33
37
|
RuntimeError: If the download fails.
|
|
34
38
|
"""
|
|
35
39
|
logger = logging.getLogger("MediaDownloader")
|
|
36
|
-
logger.debug(
|
|
40
|
+
logger.debug(
|
|
41
|
+
f"Starting download for URL: {video_url}, directory: {download_directory}, audio_only: {audio_only}"
|
|
42
|
+
)
|
|
37
43
|
|
|
38
44
|
try:
|
|
39
45
|
if not video_url:
|
media_downloader/version.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: media-downloader
|
|
3
|
-
Version: 0.11.
|
|
3
|
+
Version: 0.11.24
|
|
4
4
|
Summary: Download audio/videos from the internet!
|
|
5
5
|
Home-page: https://github.com/Knuckles-Team/media-downloader
|
|
6
6
|
Author: Audel Rouhi
|
|
@@ -45,7 +45,7 @@ Requires-Dist: yt-dlp (>=2025.8.20)
|
|
|
45
45
|

|
|
46
46
|

|
|
47
47
|
|
|
48
|
-
*Version: 0.11.
|
|
48
|
+
*Version: 0.11.24*
|
|
49
49
|
|
|
50
50
|
Download videos and audio from the internet!
|
|
51
51
|
|
|
@@ -117,16 +117,11 @@ video_downloader_instance.get_channel_videos("YT-Channel Name")
|
|
|
117
117
|
|
|
118
118
|
Use with AI
|
|
119
119
|
|
|
120
|
-
```bash
|
|
121
|
-
python -m media_downloader_mcp
|
|
122
|
-
```
|
|
123
|
-
|
|
124
120
|
```json
|
|
125
121
|
{
|
|
126
122
|
"mcpServers": {
|
|
127
123
|
"media_downloader": {
|
|
128
|
-
"command": "
|
|
129
|
-
"args": ["-m", "media_downloader_mcp"]
|
|
124
|
+
"command": "media-downloader-mcp"
|
|
130
125
|
}
|
|
131
126
|
}
|
|
132
127
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
media_downloader/__init__.py,sha256=d0PDULMlfmN1E52NKz20Wprllpq-UYMsBU3-2p4ZEk8,460
|
|
2
|
+
media_downloader/__main__.py,sha256=aHajZBE7fyiC7E5qjV5LMe9nCPkQV2YKu6FU8Ubkdm4,112
|
|
3
|
+
media_downloader/media_downloader.py,sha256=fK8CWskZQQTTZ91YnD7gJafvk5fZGp9oOOJYJy5Fwfo,8876
|
|
4
|
+
media_downloader/media_downloader_mcp.py,sha256=zJOXaKevO9PBBdmQC-I3gd1vEAJA5VsS4Kn7F58pnDk,3780
|
|
5
|
+
media_downloader/version.py,sha256=H_49aDbDI6QGW4dZQaFHOuGo2MuNkElLd647tPl5YuM,118
|
|
6
|
+
media_downloader-0.11.24.dist-info/LICENSE,sha256=Z1xmcrPHBnGCETO_LLQJUeaSNBSnuptcDVTt4kaPUOE,1060
|
|
7
|
+
media_downloader-0.11.24.dist-info/METADATA,sha256=98rG_ojIOzRnWcF1yB_7PgZi-WfqU8MwW23djNexhfI,5446
|
|
8
|
+
media_downloader-0.11.24.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
|
|
9
|
+
media_downloader-0.11.24.dist-info/entry_points.txt,sha256=Hjp1vLkHPq_bABsuh4kpL5nddi1wn9Ftota-72_GgW4,142
|
|
10
|
+
media_downloader-0.11.24.dist-info/top_level.txt,sha256=B2OBmgONOm0hIyx2HJ8qFPOI_p5HOeolrYvmslVC1fc,17
|
|
11
|
+
media_downloader-0.11.24.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
media_downloader/__init__.py,sha256=d0PDULMlfmN1E52NKz20Wprllpq-UYMsBU3-2p4ZEk8,460
|
|
2
|
-
media_downloader/__main__.py,sha256=aHajZBE7fyiC7E5qjV5LMe9nCPkQV2YKu6FU8Ubkdm4,112
|
|
3
|
-
media_downloader/media_downloader.py,sha256=26o0PORszTvcs4Lk57OFNIFb2WAD7txH0YJi-kB3xt0,9096
|
|
4
|
-
media_downloader/media_downloader_mcp.py,sha256=E5r3x5ew0eCiY916GHDmlgO-BmesykECdwDvX9IWOkQ,3654
|
|
5
|
-
media_downloader/version.py,sha256=_yr94llyGInGAEa4_ATRkLOpkGIWcuLAL0cu4f1nDPo,118
|
|
6
|
-
media_downloader-0.11.22.dist-info/LICENSE,sha256=Z1xmcrPHBnGCETO_LLQJUeaSNBSnuptcDVTt4kaPUOE,1060
|
|
7
|
-
media_downloader-0.11.22.dist-info/METADATA,sha256=aC9ddUkJbpB8FPZIYRKbwnwnxqiZAZ-VjmcTMD3NkUE,5522
|
|
8
|
-
media_downloader-0.11.22.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
|
|
9
|
-
media_downloader-0.11.22.dist-info/entry_points.txt,sha256=Hjp1vLkHPq_bABsuh4kpL5nddi1wn9Ftota-72_GgW4,142
|
|
10
|
-
media_downloader-0.11.22.dist-info/top_level.txt,sha256=B2OBmgONOm0hIyx2HJ8qFPOI_p5HOeolrYvmslVC1fc,17
|
|
11
|
-
media_downloader-0.11.22.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|