@@ -17,31 +17,41 @@ class GeminiImage(BaseModel):
1717 @classmethod
1818 def validate_images (cls , images ):
1919 if not images :
20- raise ValueError ("Input is empty. Please provide images to proceed." )
20+ raise ValueError (
21+ "Input is empty. Please provide images infomation to proceed."
22+ )
23+
24+ # Async downloader
25+ @classmethod
26+ async def save (
27+ cls ,
28+ images : List ["GeminiImage" ],
29+ save_path : str = "cached" ,
30+ cookies : Optional [dict ] = None ,
31+ ) -> Optional [Path ]:
32+ cls .validate_images (images )
33+ image_data = await cls .fetch_images_dict (images , cookies )
34+ await cls .save_images (image_data , save_path )
2135
2236 @staticmethod
23- async def fetch_bytes (url : HttpUrl ) -> Optional [bytes ]:
37+ async def fetch_bytes (
38+ url : HttpUrl , cookies : Optional [dict ] = None
39+ ) -> Optional [bytes ]:
2440 try :
2541 async with httpx .AsyncClient (follow_redirects = True ) as client :
26- response = await client .get (str (url ))
42+ response = await client .get (str (url ), cookies = cookies )
2743 response .raise_for_status ()
2844 return response .content
2945 except Exception as e :
3046 print (f"Failed to download { url } : { str (e )} " )
3147 return None
3248
3349 @classmethod
34- async def save (
35- cls , images : List ["GeminiImage" ], save_path : str = "cached"
36- ) -> Optional [Path ]:
37- cls .validate_images (images )
38- image_data = await cls .fetch_images_dict (images )
39- await cls .save_images (image_data , save_path )
40-
41- @classmethod
42- async def fetch_images_dict (cls , images : List ["GeminiImage" ]) -> Dict [str , bytes ]:
50+ async def fetch_images_dict (
51+ cls , images : List ["GeminiImage" ], cookies : Optional [dict ] = None
52+ ) -> Dict [str , bytes ]:
4353 cls .validate_images (images )
44- tasks = [cls .fetch_bytes (image .url ) for image in images ]
54+ tasks = [cls .fetch_bytes (image .url , cookies = cookies ) for image in images ]
4555 results = await asyncio .gather (* tasks )
4656 return {image .title : result for image , result in zip (images , results ) if result }
4757
@@ -59,24 +69,27 @@ async def save_images(image_data: Dict[str, bytes], save_path: str = "cached"):
5969 except Exception as e :
6070 print (f"Error saving { title } : { str (e )} " )
6171
72+ # Sync downloader
6273 @staticmethod
63- def fetch_bytes_sync (url : HttpUrl ) -> Optional [bytes ]:
64- """Synchronously fetches the bytes data of an image from the given URL.
74+ def save_sync (
75+ images : List ["GeminiImage" ],
76+ cookies : Optional [dict ] = None ,
77+ save_path : str = "cached" ,
78+ ) -> Optional [Path ]:
79+ """Synchronously saves the image to the specified path.
6580
6681 Args:
67- url (str): The URL of the image.
82+ path (str): The directory where the image will be saved.
83+ filename (str, optional): The filename for the saved image. If not provided,
84+ a filename is generated based on the image title.
85+ cookies (dict, optional): Cookies to be used for downloading the image.
6886
6987 Returns:
70- Optional[bytes ]: The bytes data of the image, or None if fetching fails.
88+ Optional[Path ]: The path where the image is saved , or None if saving fails.
7189 """
72- try :
73- with httpx .Client (follow_redirects = True ) as client :
74- response = client .get (str (url ))
75- response .raise_for_status ()
76- return response .content
77- except Exception as e :
78- print (f"Failed to download { url } : { str (e )} " )
79- return None
90+ image_data = GeminiImage .fetch_images_dict_sync (images , cookies )
91+ GeminiImage .validate_images (image_data )
92+ GeminiImage .save_images_sync (image_data , save_path )
8093
8194 @staticmethod
8295 def fetch_bytes_sync (
@@ -95,27 +108,6 @@ def fetch_bytes_sync(
95108 print (f"Failed to download { url } : { str (e )} " )
96109 pass
97110
98- @staticmethod
99- def save_sync (
100- images : List ["GeminiImage" ],
101- cookies : Optional [dict ] = None ,
102- save_path : str = "cached" ,
103- ) -> Optional [Path ]:
104- """Synchronously saves the image to the specified path.
105-
106- Args:
107- path (str): The directory where the image will be saved.
108- filename (str, optional): The filename for the saved image. If not provided,
109- a filename is generated based on the image title.
110- cookies (dict, optional): Cookies to be used for downloading the image.
111-
112- Returns:
113- Optional[Path]: The path where the image is saved, or None if saving fails.
114- """
115- image_data = GeminiImage .fetch_images_dict_sync (images , cookies )
116- GeminiImage .validate_images (image_data )
117- GeminiImage .save_images_sync (image_data , save_path )
118-
119111 @staticmethod
120112 def fetch_images_dict_sync (
121113 images : List ["GeminiImage" ], cookies : Optional [dict ] = None
0 commit comments