media-downloader 1.0.10__tar.gz → 1.0.12__tar.gz

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.

Files changed (19) hide show
  1. {media_downloader-1.0.10/media_downloader.egg-info → media_downloader-1.0.12}/PKG-INFO +2 -2
  2. {media_downloader-1.0.10 → media_downloader-1.0.12}/README.md +1 -1
  3. {media_downloader-1.0.10 → media_downloader-1.0.12}/media_downloader/__init__.py +1 -2
  4. {media_downloader-1.0.10 → media_downloader-1.0.12}/media_downloader/__main__.py +0 -1
  5. {media_downloader-1.0.10 → media_downloader-1.0.12}/media_downloader/media_downloader.py +39 -37
  6. {media_downloader-1.0.10 → media_downloader-1.0.12}/media_downloader/media_downloader_mcp.py +39 -47
  7. {media_downloader-1.0.10 → media_downloader-1.0.12/media_downloader.egg-info}/PKG-INFO +2 -2
  8. media_downloader-1.0.12/media_downloader.egg-info/entry_points.txt +3 -0
  9. {media_downloader-1.0.10 → media_downloader-1.0.12}/pyproject.toml +4 -4
  10. media_downloader-1.0.10/media_downloader.egg-info/entry_points.txt +0 -3
  11. {media_downloader-1.0.10 → media_downloader-1.0.12}/LICENSE +0 -0
  12. {media_downloader-1.0.10 → media_downloader-1.0.12}/MANIFEST.in +0 -0
  13. {media_downloader-1.0.10 → media_downloader-1.0.12}/media_downloader.egg-info/SOURCES.txt +0 -0
  14. {media_downloader-1.0.10 → media_downloader-1.0.12}/media_downloader.egg-info/dependency_links.txt +0 -0
  15. {media_downloader-1.0.10 → media_downloader-1.0.12}/media_downloader.egg-info/requires.txt +0 -0
  16. {media_downloader-1.0.10 → media_downloader-1.0.12}/media_downloader.egg-info/top_level.txt +0 -0
  17. {media_downloader-1.0.10 → media_downloader-1.0.12}/requirements.txt +0 -0
  18. {media_downloader-1.0.10 → media_downloader-1.0.12}/setup.cfg +0 -0
  19. {media_downloader-1.0.10 → media_downloader-1.0.12}/tests/test_mcp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: media-downloader
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Summary: Download audio/videos from the internet!
5
5
  Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
6
  License: MIT
@@ -38,7 +38,7 @@ Dynamic: license-file
38
38
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/media-downloader)
39
39
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/media-downloader)
40
40
 
41
- *Version: 1.0.10*
41
+ *Version: 1.0.12*
42
42
 
43
43
  Download videos and audio from the internet!
44
44
 
@@ -20,7 +20,7 @@
20
20
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/media-downloader)
21
21
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/media-downloader)
22
22
 
23
- *Version: 1.0.10*
23
+ *Version: 1.0.12*
24
24
 
25
25
  Download videos and audio from the internet!
26
26
 
@@ -3,7 +3,6 @@
3
3
 
4
4
  from media_downloader.media_downloader import (
5
5
  media_downloader,
6
- main,
7
6
  setup_logging,
8
7
  MediaDownloader,
9
8
  )
@@ -14,4 +13,4 @@ media-downloader
14
13
  Download videos and audio from the internet!
15
14
  """
16
15
 
17
- __all__ = ["media_downloader", "main", "setup_logging", "MediaDownloader"]
16
+ __all__ = ["media_downloader", "setup_logging", "MediaDownloader"]
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/python
2
2
  # coding: utf-8
3
- from .media_downloader_mcp import main
4
3
 
5
4
  if __name__ == "__main__":
6
5
  main()
@@ -4,7 +4,7 @@
4
4
  import os
5
5
  import sys
6
6
  import re
7
- import getopt
7
+ import argparse
8
8
  import logging
9
9
  import requests
10
10
  import yt_dlp
@@ -65,6 +65,12 @@ class MediaDownloader:
65
65
  def set_progress_callback(self, callback):
66
66
  self.progress_callback = callback
67
67
 
68
+ def open_file(self, file):
69
+ youtube_urls = open(file, "r")
70
+ for url in youtube_urls:
71
+ self.links.append(url)
72
+ self.links = list(dict.fromkeys(self.links))
73
+
68
74
  def download_video(self, link):
69
75
  self.logger.debug(f"Downloading video: {link}")
70
76
  outtmpl = f"{self.download_directory}/%(uploader)s - %(title)s.%(ext)s"
@@ -189,39 +195,6 @@ class MediaDownloader:
189
195
  pool.join()
190
196
 
191
197
 
192
- def media_downloader(argv):
193
- logger = setup_logging(is_mcp_server=False)
194
- video_downloader_instance = MediaDownloader()
195
- try:
196
- opts, args = getopt.getopt(
197
- argv,
198
- "hac:d:f:l:",
199
- ["help", "audio", "channel=", "directory=", "file=", "links="],
200
- )
201
- except getopt.GetoptError:
202
- usage()
203
- logger.error("Incorrect arguments")
204
- sys.exit(2)
205
- for opt, arg in opts:
206
- if opt in ("-h", "--help"):
207
- usage()
208
- sys.exit()
209
- elif opt in ("-a", "--audio"):
210
- video_downloader_instance.audio = True
211
- elif opt in ("-c", "--channel"):
212
- video_downloader_instance.get_channel_videos(arg)
213
- elif opt in ("-d", "--directory"):
214
- video_downloader_instance.download_directory = arg
215
- elif opt in ("-f", "--file"):
216
- video_downloader_instance.open_file(arg)
217
- elif opt in ("-l", "--links"):
218
- url_list = arg.replace(" ", "").split(",")
219
- for url in url_list:
220
- video_downloader_instance.links.extend(url_list)
221
-
222
- video_downloader_instance.download_all()
223
-
224
-
225
198
  def usage():
226
199
  print(
227
200
  "Media-Downloader: A tool to download any video off the internet!\n"
@@ -237,9 +210,38 @@ def usage():
237
210
  )
238
211
 
239
212
 
240
- def main():
241
- media_downloader(sys.argv[1:])
213
+ def media_downloader():
214
+ parser = argparse.ArgumentParser(description="Download media from various sources.")
215
+ parser.add_argument(
216
+ "-a", "--audio", action="store_true", help="Download audio only"
217
+ )
218
+ parser.add_argument("-c", "--channel", help="Download videos from a channel URL")
219
+ parser.add_argument("-d", "--directory", help="Specify download directory")
220
+ parser.add_argument("-f", "--file", help="Read URLs from a file")
221
+ parser.add_argument(
222
+ "-l", "--links", help="Comma-separated list of URLs to download"
223
+ )
224
+
225
+ args = parser.parse_args()
226
+
227
+ logger = setup_logging(is_mcp_server=False)
228
+ video_downloader_instance = MediaDownloader()
229
+
230
+ if args.audio:
231
+ video_downloader_instance.audio = True
232
+ if args.channel:
233
+ video_downloader_instance.get_channel_videos(args.channel)
234
+ if args.directory:
235
+ video_downloader_instance.download_directory = args.directory
236
+ if args.file:
237
+ video_downloader_instance.open_file(args.file)
238
+ if args.links:
239
+ url_list = args.links.replace(" ", "").split(",")
240
+ video_downloader_instance.links.extend(url_list)
241
+
242
+ logger.info("Kicking off downloads...")
243
+ video_downloader_instance.download_all()
242
244
 
243
245
 
244
246
  if __name__ == "__main__":
245
- media_downloader(sys.argv[1:])
247
+ media_downloader()
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/python
2
2
  # coding: utf-8
3
- import getopt
3
+ import argparse
4
4
  import os
5
5
  import sys
6
6
  import logging
@@ -14,13 +14,14 @@ setup_logging(is_mcp_server=True, log_file="media_downloader_mcp.log")
14
14
 
15
15
  mcp = FastMCP(name="MediaDownloaderServer")
16
16
 
17
+
17
18
  def to_boolean(string):
18
19
  # Normalize the string: strip whitespace and convert to lowercase
19
20
  normalized = str(string).strip().lower()
20
21
 
21
22
  # Define valid true/false values
22
- true_values = {'t', 'true', 'y', 'yes', '1'}
23
- false_values = {'f', 'false', 'n', 'no', '0'}
23
+ true_values = {"t", "true", "y", "yes", "1"}
24
+ false_values = {"f", "false", "n", "no", "0"}
24
25
 
25
26
  if normalized in true_values:
26
27
  return True
@@ -29,11 +30,6 @@ def to_boolean(string):
29
30
  else:
30
31
  raise ValueError(f"Cannot convert '{string}' to boolean")
31
32
 
32
- environment_download_directory = os.environ.get("DOWNLOAD_DIRECTORY", None)
33
- environment_audio_only = os.environ.get("AUDIO_ONLY", False)
34
-
35
- if environment_audio_only:
36
- environment_audio_only = to_boolean(environment_audio_only)
37
33
 
38
34
  @mcp.tool(
39
35
  annotations={
@@ -49,9 +45,15 @@ async def download_media(
49
45
  video_url: str = Field(description="Video URL to Download", default=None),
50
46
  download_directory: Optional[str] = Field(
51
47
  description="The directory where the media will be saved. If None, uses default directory.",
52
- default=environment_download_directory),
53
- audio_only: Optional[bool] = Field(description="Downloads only the audio", default=environment_audio_only),
54
- ctx: Context = Field(description="MCP context for progress reporting.", default=None),
48
+ default=os.environ.get("DOWNLOAD_DIRECTORY", None),
49
+ ),
50
+ audio_only: Optional[bool] = Field(
51
+ description="Downloads only the audio",
52
+ default=to_boolean(os.environ.get("AUDIO_ONLY", False)),
53
+ ),
54
+ ctx: Context = Field(
55
+ description="MCP context for progress reporting.", default=None
56
+ ),
55
57
  ) -> str:
56
58
  """Downloads media from a given URL to the specified directory."""
57
59
  logger = logging.getLogger("MediaDownloader")
@@ -101,47 +103,37 @@ async def download_media(
101
103
  raise RuntimeError(f"Failed to download media: {str(e)}")
102
104
 
103
105
 
104
- def media_downloader_mcp(argv):
105
- transport = "stdio"
106
- host = "0.0.0.0"
107
- port = 8000
108
- try:
109
- opts, args = getopt.getopt(
110
- argv,
111
- "ht:h:p:",
112
- ["help", "transport=", "host=", "port="],
113
- )
114
- except getopt.GetoptError:
115
- sys.exit(2)
116
- for opt, arg in opts:
117
- if opt in ("-h", "--help"):
118
- sys.exit()
119
- elif opt in ("-t", "--transport"):
120
- transport = arg
121
- elif opt in ("-h", "--host"):
122
- host = arg
123
- elif opt in ("-p", "--port"):
124
- try:
125
- port = int(arg) # Attempt to convert port to integer
126
- if not (0 <= port <= 65535): # Valid port range
127
- print(f"Error: Port {arg} is out of valid range (0-65535).")
128
- sys.exit(1)
129
- except ValueError:
130
- print(f"Error: Port {arg} is not a valid integer.")
131
- sys.exit(1)
132
- if transport == "stdio":
106
+ def media_downloader_mcp():
107
+ parser = argparse.ArgumentParser(description="Run media downloader MCP server.")
108
+ parser.add_argument(
109
+ "-t",
110
+ "--transport",
111
+ default="stdio",
112
+ choices=["stdio", "http"],
113
+ help="Transport method (stdio or http, default: stdio)",
114
+ )
115
+ parser.add_argument(
116
+ "-h", "--host", default="0.0.0.0", help="Host address (default: 0.0.0.0)"
117
+ )
118
+ parser.add_argument(
119
+ "-p", "--port", type=int, default=8000, help="Port number (default: 8000)"
120
+ )
121
+
122
+ args = parser.parse_args()
123
+
124
+ if args.port < 0 or args.port > 65535:
125
+ print(f"Error: Port {args.port} is out of valid range (0-65535).")
126
+ sys.exit(1)
127
+
128
+ if args.transport == "stdio":
133
129
  mcp.run(transport="stdio")
134
- elif transport == "http":
135
- mcp.run(transport="http", host=host, port=port)
130
+ elif args.transport == "http":
131
+ mcp.run(transport="http", host=args.host, port=args.port)
136
132
  else:
137
133
  logger = logging.getLogger("MediaDownloader")
138
134
  logger.error("Transport not supported")
139
135
  sys.exit(1)
140
136
 
141
137
 
142
- def main():
143
- media_downloader_mcp(sys.argv[1:])
144
-
145
-
146
138
  if __name__ == "__main__":
147
- media_downloader_mcp(sys.argv[1:])
139
+ media_downloader_mcp()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: media-downloader
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Summary: Download audio/videos from the internet!
5
5
  Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
6
  License: MIT
@@ -38,7 +38,7 @@ Dynamic: license-file
38
38
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/media-downloader)
39
39
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/media-downloader)
40
40
 
41
- *Version: 1.0.10*
41
+ *Version: 1.0.12*
42
42
 
43
43
  Download videos and audio from the internet!
44
44
 
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ media-downloader = media_downloader.media_downloader:media_downloader
3
+ media-downloader-mcp = media_downloader.media_downloader_mcp:media_downloader_mcp
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "media-downloader"
7
- version = "1.0.10"
7
+ version = "1.0.12"
8
8
  description = "Download audio/videos from the internet!\nHost an MCP Server for Agentic AI to download videos!"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "Audel Rouhi", email = "knucklessg1@gmail.com" }]
@@ -23,12 +23,12 @@ dependencies = [
23
23
  ]
24
24
 
25
25
  [project.scripts]
26
- media-downloader = "media_downloader.media_downloader:main"
27
- media-downloader-mcp = "media_downloader.media_downloader_mcp:main"
26
+ media-downloader = "media_downloader.media_downloader:media_downloader"
27
+ media-downloader-mcp = "media_downloader.media_downloader_mcp:media_downloader_mcp"
28
28
 
29
29
  [tool.setuptools.packages.find]
30
30
  where = ["."]
31
31
 
32
32
  [tool.setuptools]
33
33
  include-package-data = true
34
- package-data = { "media_downloader" = ["media_downloader"] }
34
+ package-data = { "media_downloader" = ["media_downloader"] }
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- media-downloader = media_downloader.media_downloader:main
3
- media-downloader-mcp = media_downloader.media_downloader_mcp:main