whatsapp-python 3.3.5.dev0__py3-none-any.whl → 3.3.9__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.
- whatsapp/__init__.py +386 -386
- whatsapp/constants.py +4 -4
- whatsapp/ext/_buttons.py +82 -82
- whatsapp/ext/_media.py +135 -135
- whatsapp/ext/_message.py +124 -124
- whatsapp/ext/_property.py +5 -5
- whatsapp/ext/_send_media.py +364 -267
- whatsapp/ext/_send_others.py +118 -86
- whatsapp/ext/_static.py +329 -329
- {whatsapp_python-3.3.5.dev0.dist-info → whatsapp_python-3.3.9.dist-info}/METADATA +1 -1
- whatsapp_python-3.3.9.dist-info/RECORD +13 -0
- {whatsapp_python-3.3.5.dev0.dist-info → whatsapp_python-3.3.9.dist-info}/licenses/LICENSE +21 -21
- whatsapp_python-3.3.5.dev0.dist-info/RECORD +0 -13
- {whatsapp_python-3.3.5.dev0.dist-info → whatsapp_python-3.3.9.dist-info}/WHEEL +0 -0
whatsapp/constants.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# This file contains the constants used in the project.
|
|
2
|
-
# The VERSION constant is used to store the version of the project - it's not only used in the __init__.py file, but also in the pyproject.toml file.
|
|
3
|
-
|
|
4
|
-
VERSION = "3.3.
|
|
1
|
+
# This file contains the constants used in the project.
|
|
2
|
+
# The VERSION constant is used to store the version of the project - it's not only used in the __init__.py file, but also in the pyproject.toml file.
|
|
3
|
+
|
|
4
|
+
VERSION = "3.3.9"
|
whatsapp/ext/_buttons.py
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import requests
|
|
3
|
-
from typing import Dict, Any
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def create_button(self, button: Dict[Any, Any]) -> Dict[Any, Any]:
|
|
7
|
-
"""
|
|
8
|
-
Method to create a button object to be used in the send_message method.
|
|
9
|
-
|
|
10
|
-
This is method is designed to only be used internally by the send_button method.
|
|
11
|
-
|
|
12
|
-
Args:
|
|
13
|
-
button[dict]: A dictionary containing the button data
|
|
14
|
-
"""
|
|
15
|
-
data = {"type": "list", "action": button.get("action")}
|
|
16
|
-
if button.get("header"):
|
|
17
|
-
data["header"] = {"type": "text", "text": button.get("header")}
|
|
18
|
-
if button.get("body"):
|
|
19
|
-
data["body"] = {"text": button.get("body")}
|
|
20
|
-
if button.get("footer"):
|
|
21
|
-
data["footer"] = {"text": button.get("footer")}
|
|
22
|
-
return data
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def send_button(self, button: Dict[Any, Any], recipient_id: str) -> Dict[Any, Any]:
|
|
26
|
-
"""
|
|
27
|
-
Sends an interactive buttons message to a WhatsApp user
|
|
28
|
-
|
|
29
|
-
Args:
|
|
30
|
-
button[dict]: A dictionary containing the button data(rows-title may not exceed 20 characters)
|
|
31
|
-
recipient_id[str]: Phone number of the user with country code wihout +
|
|
32
|
-
|
|
33
|
-
check https://github.com/Neurotech-HQ/whatsapp#sending-interactive-reply-buttons for an example.
|
|
34
|
-
"""
|
|
35
|
-
data = {
|
|
36
|
-
"messaging_product": "whatsapp",
|
|
37
|
-
"to": recipient_id,
|
|
38
|
-
"type": "interactive",
|
|
39
|
-
"interactive": self.create_button(button),
|
|
40
|
-
}
|
|
41
|
-
logging.info(f"Sending buttons to {recipient_id}")
|
|
42
|
-
r = requests.post(self.url, headers=self.headers, json=data)
|
|
43
|
-
if r.status_code == 200:
|
|
44
|
-
logging.info(f"Buttons sent to {recipient_id}")
|
|
45
|
-
return r.json()
|
|
46
|
-
logging.info(f"Buttons not sent to {recipient_id}")
|
|
47
|
-
logging.info(f"Status code: {r.status_code}")
|
|
48
|
-
logging.info(f"Response: {r.json()}")
|
|
49
|
-
return r.json()
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def send_reply_button(
|
|
53
|
-
self, button: Dict[Any, Any], recipient_id: str
|
|
54
|
-
) -> Dict[Any, Any]:
|
|
55
|
-
"""
|
|
56
|
-
Sends an interactive reply buttons[menu] message to a WhatsApp user
|
|
57
|
-
|
|
58
|
-
Args:
|
|
59
|
-
button[dict]: A dictionary containing the button data
|
|
60
|
-
recipient_id[str]: Phone number of the user with country code wihout +
|
|
61
|
-
|
|
62
|
-
Note:
|
|
63
|
-
The maximum number of buttons is 3, more than 3 buttons will rise an error.
|
|
64
|
-
"""
|
|
65
|
-
if len(button["action"]["buttons"]) > 3:
|
|
66
|
-
raise ValueError("The maximum number of buttons is 3.")
|
|
67
|
-
|
|
68
|
-
data = {
|
|
69
|
-
"messaging_product": "whatsapp",
|
|
70
|
-
"recipient_type": "individual",
|
|
71
|
-
"to": recipient_id,
|
|
72
|
-
"type": "interactive",
|
|
73
|
-
"interactive": button,
|
|
74
|
-
}
|
|
75
|
-
r = requests.post(self.url, headers=self.headers, json=data)
|
|
76
|
-
if r.status_code == 200:
|
|
77
|
-
logging.info(f"Reply buttons sent to {recipient_id}")
|
|
78
|
-
return r.json()
|
|
79
|
-
logging.info(f"Reply buttons not sent to {recipient_id}")
|
|
80
|
-
logging.info(f"Status code: {r.status_code}")
|
|
81
|
-
logging.info(f"Response: {r.json()}")
|
|
82
|
-
return r.json()
|
|
1
|
+
import logging
|
|
2
|
+
import requests
|
|
3
|
+
from typing import Dict, Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def create_button(self, button: Dict[Any, Any]) -> Dict[Any, Any]:
|
|
7
|
+
"""
|
|
8
|
+
Method to create a button object to be used in the send_message method.
|
|
9
|
+
|
|
10
|
+
This is method is designed to only be used internally by the send_button method.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
button[dict]: A dictionary containing the button data
|
|
14
|
+
"""
|
|
15
|
+
data = {"type": "list", "action": button.get("action")}
|
|
16
|
+
if button.get("header"):
|
|
17
|
+
data["header"] = {"type": "text", "text": button.get("header")}
|
|
18
|
+
if button.get("body"):
|
|
19
|
+
data["body"] = {"text": button.get("body")}
|
|
20
|
+
if button.get("footer"):
|
|
21
|
+
data["footer"] = {"text": button.get("footer")}
|
|
22
|
+
return data
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def send_button(self, button: Dict[Any, Any], recipient_id: str) -> Dict[Any, Any]:
|
|
26
|
+
"""
|
|
27
|
+
Sends an interactive buttons message to a WhatsApp user
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
button[dict]: A dictionary containing the button data(rows-title may not exceed 20 characters)
|
|
31
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
32
|
+
|
|
33
|
+
check https://github.com/Neurotech-HQ/whatsapp#sending-interactive-reply-buttons for an example.
|
|
34
|
+
"""
|
|
35
|
+
data = {
|
|
36
|
+
"messaging_product": "whatsapp",
|
|
37
|
+
"to": recipient_id,
|
|
38
|
+
"type": "interactive",
|
|
39
|
+
"interactive": self.create_button(button),
|
|
40
|
+
}
|
|
41
|
+
logging.info(f"Sending buttons to {recipient_id}")
|
|
42
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
43
|
+
if r.status_code == 200:
|
|
44
|
+
logging.info(f"Buttons sent to {recipient_id}")
|
|
45
|
+
return r.json()
|
|
46
|
+
logging.info(f"Buttons not sent to {recipient_id}")
|
|
47
|
+
logging.info(f"Status code: {r.status_code}")
|
|
48
|
+
logging.info(f"Response: {r.json()}")
|
|
49
|
+
return r.json()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def send_reply_button(
|
|
53
|
+
self, button: Dict[Any, Any], recipient_id: str
|
|
54
|
+
) -> Dict[Any, Any]:
|
|
55
|
+
"""
|
|
56
|
+
Sends an interactive reply buttons[menu] message to a WhatsApp user
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
button[dict]: A dictionary containing the button data
|
|
60
|
+
recipient_id[str]: Phone number of the user with country code wihout +
|
|
61
|
+
|
|
62
|
+
Note:
|
|
63
|
+
The maximum number of buttons is 3, more than 3 buttons will rise an error.
|
|
64
|
+
"""
|
|
65
|
+
if len(button["action"]["buttons"]) > 3:
|
|
66
|
+
raise ValueError("The maximum number of buttons is 3.")
|
|
67
|
+
|
|
68
|
+
data = {
|
|
69
|
+
"messaging_product": "whatsapp",
|
|
70
|
+
"recipient_type": "individual",
|
|
71
|
+
"to": recipient_id,
|
|
72
|
+
"type": "interactive",
|
|
73
|
+
"interactive": button,
|
|
74
|
+
}
|
|
75
|
+
r = requests.post(self.url, headers=self.headers, json=data)
|
|
76
|
+
if r.status_code == 200:
|
|
77
|
+
logging.info(f"Reply buttons sent to {recipient_id}")
|
|
78
|
+
return r.json()
|
|
79
|
+
logging.info(f"Reply buttons not sent to {recipient_id}")
|
|
80
|
+
logging.info(f"Status code: {r.status_code}")
|
|
81
|
+
logging.info(f"Response: {r.json()}")
|
|
82
|
+
return r.json()
|
whatsapp/ext/_media.py
CHANGED
|
@@ -1,135 +1,135 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import requests
|
|
3
|
-
import os
|
|
4
|
-
import mimetypes
|
|
5
|
-
from requests_toolbelt.multipart.encoder import MultipartEncoder
|
|
6
|
-
from typing import Union, Dict, Any
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def upload_media(self, media: str) -> Union[Dict[Any, Any], None]:
|
|
10
|
-
"""
|
|
11
|
-
Uploads a media to the cloud api and returns the id of the media
|
|
12
|
-
|
|
13
|
-
Args:
|
|
14
|
-
media[str]: Path of the media to be uploaded
|
|
15
|
-
|
|
16
|
-
Example:
|
|
17
|
-
>>> from whatsapp import WhatsApp
|
|
18
|
-
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
19
|
-
>>> whatsapp.upload_media("/path/to/media")
|
|
20
|
-
|
|
21
|
-
REFERENCE: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#
|
|
22
|
-
"""
|
|
23
|
-
form_data = {
|
|
24
|
-
"file": (
|
|
25
|
-
media,
|
|
26
|
-
open(os.path.realpath(media), "rb"),
|
|
27
|
-
mimetypes.guess_type(media)[0],
|
|
28
|
-
),
|
|
29
|
-
"messaging_product": "whatsapp",
|
|
30
|
-
"type": mimetypes.guess_type(media)[0],
|
|
31
|
-
}
|
|
32
|
-
form_data = MultipartEncoder(fields=form_data)
|
|
33
|
-
headers = self.headers.copy()
|
|
34
|
-
headers["Content-Type"] = form_data.content_type
|
|
35
|
-
logging.info(f"Content-Type: {form_data.content_type}")
|
|
36
|
-
logging.info(f"Uploading media {media}")
|
|
37
|
-
r = requests.post(
|
|
38
|
-
f"{self.base_url}/{self.phone_number_id}/media",
|
|
39
|
-
headers=headers,
|
|
40
|
-
data=form_data,
|
|
41
|
-
)
|
|
42
|
-
if r.status_code == 200:
|
|
43
|
-
logging.info(f"Media {media} uploaded")
|
|
44
|
-
return r.json()
|
|
45
|
-
logging.info(f"Error uploading media {media}")
|
|
46
|
-
logging.info(f"Status code: {r.status_code}")
|
|
47
|
-
logging.debug(f"Response: {r.json()}")
|
|
48
|
-
return None
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def delete_media(self, media_id: str) -> Union[Dict[Any, Any], None]:
|
|
52
|
-
"""
|
|
53
|
-
Deletes a media from the cloud api
|
|
54
|
-
|
|
55
|
-
Args:
|
|
56
|
-
media_id[str]: Id of the media to be deleted
|
|
57
|
-
"""
|
|
58
|
-
logging.info(f"Deleting media {media_id}")
|
|
59
|
-
r = requests.delete(
|
|
60
|
-
f"{self.base_url}/{media_id}", headers=self.headers)
|
|
61
|
-
if r.status_code == 200:
|
|
62
|
-
logging.info(f"Media {media_id} deleted")
|
|
63
|
-
return r.json()
|
|
64
|
-
logging.info(f"Error deleting media {media_id}")
|
|
65
|
-
logging.info(f"Status code: {r.status_code}")
|
|
66
|
-
logging.info(f"Response: {r.json()}")
|
|
67
|
-
return None
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def query_media_url(self, media_id: str) -> Union[str, None]:
|
|
71
|
-
"""
|
|
72
|
-
Query media url from media id obtained either by manually uploading media or received media
|
|
73
|
-
|
|
74
|
-
Args:
|
|
75
|
-
media_id[str]: Media id of the media
|
|
76
|
-
|
|
77
|
-
Returns:
|
|
78
|
-
str: Media url
|
|
79
|
-
|
|
80
|
-
Example:
|
|
81
|
-
>>> from whatsapp import WhatsApp
|
|
82
|
-
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
83
|
-
>>> whatsapp.query_media_url("media_id")
|
|
84
|
-
"""
|
|
85
|
-
|
|
86
|
-
logging.info(f"Querying media url for {media_id}")
|
|
87
|
-
r = requests.get(f"{self.base_url}/{media_id}", headers=self.headers)
|
|
88
|
-
if r.status_code == 200:
|
|
89
|
-
logging.info(f"Media url queried for {media_id}")
|
|
90
|
-
return r.json()["url"]
|
|
91
|
-
logging.info(f"Media url not queried for {media_id}")
|
|
92
|
-
logging.info(f"Status code: {r.status_code}")
|
|
93
|
-
logging.info(f"Response: {r.json()}")
|
|
94
|
-
return None
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def download_media(
|
|
98
|
-
self, media_url: str, mime_type: str, file_path: str = "temp"
|
|
99
|
-
) -> Union[str, None]:
|
|
100
|
-
"""
|
|
101
|
-
Download media from media url obtained either by manually uploading media or received media
|
|
102
|
-
|
|
103
|
-
Args:
|
|
104
|
-
media_url[str]: Media url of the media
|
|
105
|
-
mime_type[str]: Mime type of the media
|
|
106
|
-
file_path[str]: Path of the file to be downloaded to. Default is "temp"
|
|
107
|
-
Do not include the file extension. It will be added automatically.
|
|
108
|
-
|
|
109
|
-
Returns:
|
|
110
|
-
str: Media url
|
|
111
|
-
|
|
112
|
-
Example:
|
|
113
|
-
>>> from whatsapp import WhatsApp
|
|
114
|
-
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
115
|
-
>>> whatsapp.download_media("media_url", "image/jpeg")
|
|
116
|
-
>>> whatsapp.download_media("media_url", "video/mp4", "path/to/file") #do not include the file extension
|
|
117
|
-
"""
|
|
118
|
-
r = requests.get(media_url, headers=self.headers)
|
|
119
|
-
content = r.content
|
|
120
|
-
extension = mime_type.split("/")[1]
|
|
121
|
-
save_file_here = None
|
|
122
|
-
# create a temporary file
|
|
123
|
-
try:
|
|
124
|
-
|
|
125
|
-
save_file_here = (
|
|
126
|
-
f"{file_path}.{extension}" if file_path else f"temp.{extension}"
|
|
127
|
-
)
|
|
128
|
-
with open(save_file_here, "wb") as f:
|
|
129
|
-
f.write(content)
|
|
130
|
-
logging.info(f"Media downloaded to {save_file_here}")
|
|
131
|
-
return f.name
|
|
132
|
-
except Exception as e:
|
|
133
|
-
logging.info(e)
|
|
134
|
-
logging.error(f"Error downloading media to {save_file_here}")
|
|
135
|
-
return None
|
|
1
|
+
import logging
|
|
2
|
+
import requests
|
|
3
|
+
import os
|
|
4
|
+
import mimetypes
|
|
5
|
+
from requests_toolbelt.multipart.encoder import MultipartEncoder
|
|
6
|
+
from typing import Union, Dict, Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def upload_media(self, media: str) -> Union[Dict[Any, Any], None]:
|
|
10
|
+
"""
|
|
11
|
+
Uploads a media to the cloud api and returns the id of the media
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
media[str]: Path of the media to be uploaded
|
|
15
|
+
|
|
16
|
+
Example:
|
|
17
|
+
>>> from whatsapp import WhatsApp
|
|
18
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
19
|
+
>>> whatsapp.upload_media("/path/to/media")
|
|
20
|
+
|
|
21
|
+
REFERENCE: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/media#
|
|
22
|
+
"""
|
|
23
|
+
form_data = {
|
|
24
|
+
"file": (
|
|
25
|
+
media,
|
|
26
|
+
open(os.path.realpath(media), "rb"),
|
|
27
|
+
mimetypes.guess_type(media)[0],
|
|
28
|
+
),
|
|
29
|
+
"messaging_product": "whatsapp",
|
|
30
|
+
"type": mimetypes.guess_type(media)[0],
|
|
31
|
+
}
|
|
32
|
+
form_data = MultipartEncoder(fields=form_data)
|
|
33
|
+
headers = self.headers.copy()
|
|
34
|
+
headers["Content-Type"] = form_data.content_type
|
|
35
|
+
logging.info(f"Content-Type: {form_data.content_type}")
|
|
36
|
+
logging.info(f"Uploading media {media}")
|
|
37
|
+
r = requests.post(
|
|
38
|
+
f"{self.base_url}/{self.phone_number_id}/media",
|
|
39
|
+
headers=headers,
|
|
40
|
+
data=form_data,
|
|
41
|
+
)
|
|
42
|
+
if r.status_code == 200:
|
|
43
|
+
logging.info(f"Media {media} uploaded")
|
|
44
|
+
return r.json()
|
|
45
|
+
logging.info(f"Error uploading media {media}")
|
|
46
|
+
logging.info(f"Status code: {r.status_code}")
|
|
47
|
+
logging.debug(f"Response: {r.json()}")
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def delete_media(self, media_id: str) -> Union[Dict[Any, Any], None]:
|
|
52
|
+
"""
|
|
53
|
+
Deletes a media from the cloud api
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
media_id[str]: Id of the media to be deleted
|
|
57
|
+
"""
|
|
58
|
+
logging.info(f"Deleting media {media_id}")
|
|
59
|
+
r = requests.delete(
|
|
60
|
+
f"{self.base_url}/{media_id}", headers=self.headers)
|
|
61
|
+
if r.status_code == 200:
|
|
62
|
+
logging.info(f"Media {media_id} deleted")
|
|
63
|
+
return r.json()
|
|
64
|
+
logging.info(f"Error deleting media {media_id}")
|
|
65
|
+
logging.info(f"Status code: {r.status_code}")
|
|
66
|
+
logging.info(f"Response: {r.json()}")
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def query_media_url(self, media_id: str) -> Union[str, None]:
|
|
71
|
+
"""
|
|
72
|
+
Query media url from media id obtained either by manually uploading media or received media
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
media_id[str]: Media id of the media
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
str: Media url
|
|
79
|
+
|
|
80
|
+
Example:
|
|
81
|
+
>>> from whatsapp import WhatsApp
|
|
82
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
83
|
+
>>> whatsapp.query_media_url("media_id")
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
logging.info(f"Querying media url for {media_id}")
|
|
87
|
+
r = requests.get(f"{self.base_url}/{media_id}", headers=self.headers)
|
|
88
|
+
if r.status_code == 200:
|
|
89
|
+
logging.info(f"Media url queried for {media_id}")
|
|
90
|
+
return r.json()["url"]
|
|
91
|
+
logging.info(f"Media url not queried for {media_id}")
|
|
92
|
+
logging.info(f"Status code: {r.status_code}")
|
|
93
|
+
logging.info(f"Response: {r.json()}")
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def download_media(
|
|
98
|
+
self, media_url: str, mime_type: str, file_path: str = "temp"
|
|
99
|
+
) -> Union[str, None]:
|
|
100
|
+
"""
|
|
101
|
+
Download media from media url obtained either by manually uploading media or received media
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
media_url[str]: Media url of the media
|
|
105
|
+
mime_type[str]: Mime type of the media
|
|
106
|
+
file_path[str]: Path of the file to be downloaded to. Default is "temp"
|
|
107
|
+
Do not include the file extension. It will be added automatically.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
str: Media url
|
|
111
|
+
|
|
112
|
+
Example:
|
|
113
|
+
>>> from whatsapp import WhatsApp
|
|
114
|
+
>>> whatsapp = WhatsApp(token, phone_number_id)
|
|
115
|
+
>>> whatsapp.download_media("media_url", "image/jpeg")
|
|
116
|
+
>>> whatsapp.download_media("media_url", "video/mp4", "path/to/file") #do not include the file extension
|
|
117
|
+
"""
|
|
118
|
+
r = requests.get(media_url, headers=self.headers)
|
|
119
|
+
content = r.content
|
|
120
|
+
extension = mime_type.split("/")[1]
|
|
121
|
+
save_file_here = None
|
|
122
|
+
# create a temporary file
|
|
123
|
+
try:
|
|
124
|
+
|
|
125
|
+
save_file_here = (
|
|
126
|
+
f"{file_path}.{extension}" if file_path else f"temp.{extension}"
|
|
127
|
+
)
|
|
128
|
+
with open(save_file_here, "wb") as f:
|
|
129
|
+
f.write(content)
|
|
130
|
+
logging.info(f"Media downloaded to {save_file_here}")
|
|
131
|
+
return f.name
|
|
132
|
+
except Exception as e:
|
|
133
|
+
logging.info(e)
|
|
134
|
+
logging.error(f"Error downloading media to {save_file_here}")
|
|
135
|
+
return None
|