media-downloader 0.11.21__py2.py3-none-any.whl → 0.11.23__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 +11 -5
- media_downloader/version.py +1 -1
- {media_downloader-0.11.21.dist-info → media_downloader-0.11.23.dist-info}/METADATA +2 -2
- media_downloader-0.11.23.dist-info/RECORD +11 -0
- media_downloader-0.11.21.dist-info/RECORD +0 -11
- {media_downloader-0.11.21.dist-info → media_downloader-0.11.23.dist-info}/LICENSE +0 -0
- {media_downloader-0.11.21.dist-info → media_downloader-0.11.23.dist-info}/WHEEL +0 -0
- {media_downloader-0.11.21.dist-info → media_downloader-0.11.23.dist-info}/entry_points.txt +0 -0
- {media_downloader-0.11.21.dist-info → media_downloader-0.11.23.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:
|
|
@@ -109,7 +115,7 @@ def media_downloader_mcp(argv):
|
|
|
109
115
|
|
|
110
116
|
|
|
111
117
|
def main():
|
|
112
|
-
|
|
118
|
+
media_downloader_mcp(sys.argv[1:])
|
|
113
119
|
|
|
114
120
|
|
|
115
121
|
if __name__ == "__main__":
|
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.23
|
|
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.23*
|
|
49
49
|
|
|
50
50
|
Download videos and audio from the internet!
|
|
51
51
|
|
|
@@ -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=-FvewQrvJKpPjsUeOjUwPrvYixuOCJLRq-wapfVyej0,118
|
|
6
|
+
media_downloader-0.11.23.dist-info/LICENSE,sha256=Z1xmcrPHBnGCETO_LLQJUeaSNBSnuptcDVTt4kaPUOE,1060
|
|
7
|
+
media_downloader-0.11.23.dist-info/METADATA,sha256=5FH_uCi8WAP80UYZfiuzeAMCBaOv8uiU-xtkQK5RzCM,5522
|
|
8
|
+
media_downloader-0.11.23.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
|
|
9
|
+
media_downloader-0.11.23.dist-info/entry_points.txt,sha256=Hjp1vLkHPq_bABsuh4kpL5nddi1wn9Ftota-72_GgW4,142
|
|
10
|
+
media_downloader-0.11.23.dist-info/top_level.txt,sha256=B2OBmgONOm0hIyx2HJ8qFPOI_p5HOeolrYvmslVC1fc,17
|
|
11
|
+
media_downloader-0.11.23.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=tFNLuZ54t68DiH1Ak3F10_v1Mxi0Kid-LKCfleRqCH4,3646
|
|
5
|
-
media_downloader/version.py,sha256=80Iz1aYF7oJ7XbOjepmIlgAyTL8H5hK3ALLfooDSfGg,118
|
|
6
|
-
media_downloader-0.11.21.dist-info/LICENSE,sha256=Z1xmcrPHBnGCETO_LLQJUeaSNBSnuptcDVTt4kaPUOE,1060
|
|
7
|
-
media_downloader-0.11.21.dist-info/METADATA,sha256=xuJiXbmcMeONnFKKIt5I3Zjg0AVLeLnxtLq2CQOOnpg,5522
|
|
8
|
-
media_downloader-0.11.21.dist-info/WHEEL,sha256=bb2Ot9scclHKMOLDEHY6B2sicWOgugjFKaJsT7vwMQo,110
|
|
9
|
-
media_downloader-0.11.21.dist-info/entry_points.txt,sha256=Hjp1vLkHPq_bABsuh4kpL5nddi1wn9Ftota-72_GgW4,142
|
|
10
|
-
media_downloader-0.11.21.dist-info/top_level.txt,sha256=B2OBmgONOm0hIyx2HJ8qFPOI_p5HOeolrYvmslVC1fc,17
|
|
11
|
-
media_downloader-0.11.21.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|