MagicFeedback 0.0.2__tar.gz → 0.0.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MagicFeedback
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: SDK for MagicFeedback API
5
5
  Author-email: Francisco Arias <farias@magicfedback.io>
6
6
  Project-URL: Homepage, https://github.com/MagicFeedback/magicfeedback_python_sdk
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "MagicFeedback"
3
- version = "0.0.2"
3
+ version = "0.0.3"
4
4
  authors = [
5
5
  { name="Francisco Arias", email="farias@magicfedback.io" },
6
6
  ]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: MagicFeedback
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: SDK for MagicFeedback API
5
5
  Author-email: Francisco Arias <farias@magicfedback.io>
6
6
  Project-URL: Homepage, https://github.com/MagicFeedback/magicfeedback_python_sdk
@@ -8,4 +8,6 @@ src/MagicFeedback.egg-info/SOURCES.txt
8
8
  src/MagicFeedback.egg-info/dependency_links.txt
9
9
  src/MagicFeedback.egg-info/top_level.txt
10
10
  tests/test_apikey.py
11
+ tests/test_campaign.py
12
+ tests/test_contact.py
11
13
  tests/test_feedback_create.py
@@ -0,0 +1,276 @@
1
+ import json
2
+ from typing import Any, Dict
3
+
4
+ import requests
5
+
6
+
7
+ class MagicFeedbackClient:
8
+ """A Python SDK for interacting with the MagicFeedback API."""
9
+
10
+ def __init__(self, user: str, password: str, base_url: str = "https://api.magicfeedback.io", ip_key: str = 'AIzaSyAKcR895VURSQZSN2T_RD6jX_9y5HRmH80'):
11
+
12
+ self.base_url = base_url
13
+ self.ip_key = ip_key
14
+
15
+ self.api_key = self.get_api_key(user, password)
16
+ print("API Key: ", self.api_key)
17
+ self.headers = {"Authorization": f"Bearer {self.api_key}"}
18
+
19
+ def get_api_key(self, user, password):
20
+ """Obtains the API key using user and password authentication."""
21
+ # TODO: Implement control to check if the token is still valid - Only for 1 hour
22
+ # Call your existing function
23
+ id_token = self.identity_login(user, password)
24
+ return id_token
25
+
26
+ def identity_login(self, user, password):
27
+ """
28
+ (Replace this function with your existing `identity_login` function)
29
+
30
+ Performs user and password-based login using the identity toolkit API.
31
+
32
+ Returns:
33
+ str: The obtained ID token.
34
+ """
35
+ # TODO: Control in case the call is not good
36
+ print("Logging in with user and password...")
37
+ print("User: ", user)
38
+ print("Password: ", password)
39
+
40
+ options = {
41
+ "method": "POST",
42
+ "url": "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=" + self.ip_key,
43
+ "headers": {
44
+ "Content-Type": "application/javascript",
45
+ },
46
+ "data": json.dumps({
47
+ "email": user,
48
+ "password": password,
49
+ "returnSecureToken": True
50
+ })
51
+ }
52
+
53
+ response = requests.post(
54
+ options["url"], headers=options["headers"], data=options["data"])
55
+ data = json.loads(response.text)
56
+ return data["idToken"]
57
+
58
+ def _make_request(
59
+ self, method: str, url: str, json: Dict[str, Any] = None
60
+ ) -> Dict[str, Any]:
61
+ """Makes a request to the MagicFeedback API."""
62
+ # TODO: Control token expiration
63
+ response = requests.request(
64
+ method, url, headers=self.headers, json=json)
65
+ response.raise_for_status() # Raise exception for non-2xx status codes
66
+ # TODO: Control the status of the call
67
+ print("Status code: ", response.status_code)
68
+ print("Response: ", response.json())
69
+
70
+ return response.json()
71
+
72
+ ####################################################################################
73
+ # Feedback API Methods #
74
+ ####################################################################################
75
+
76
+ def create_feedback(self, feedback: Dict[str, Any]) -> Dict[str, Any]:
77
+ """Creates a new feedback item.
78
+
79
+ Args:
80
+ feedback (Dict[str, Any]): The feedback data to create.
81
+
82
+ Returns:
83
+ Dict[str, Any]: The created feedback item.
84
+ """
85
+ url = f"{self.base_url}/feedbacks"
86
+
87
+ # Ensure required fields are present
88
+ required_fields = [
89
+ "name", "type", "identity",
90
+ "integrationId", "companyId",
91
+ "productId"
92
+ ]
93
+ for field in required_fields:
94
+ if field not in feedback:
95
+ raise ValueError(f"Missing required field: {field}")
96
+
97
+ return self._make_request("POST", url, json=feedback)
98
+
99
+ def get_feedback(self, feedback_id: str) -> Dict[str, Any]:
100
+ """Retrieves a specific feedback item.
101
+
102
+ Args:
103
+ feedback_id (str): The ID of the feedback item.
104
+
105
+ Returns:
106
+ Dict[str, Any]: The retrieved feedback item.
107
+ """
108
+ url = f"{self.base_url}/feedbacks/{feedback_id}"
109
+ return self._make_request("GET", url)
110
+
111
+ def update_feedback(self, feedback_id: str, feedback: Dict[str, Any]) -> Dict[str, Any]:
112
+ """Updates a specific feedback item.
113
+
114
+ Args:
115
+ feedback_id (str): The ID of the feedback item.
116
+ feedback (Dict[str, Any]): The updated feedback data.
117
+
118
+ Returns:
119
+ Dict[str, Any]: The updated feedback item.
120
+ """
121
+ url = f"{self.base_url}/feedbacks/{feedback_id}"
122
+ return self._make_request("PUT", url, json=feedback)
123
+
124
+ def delete_feedback(self, feedback_id: str) -> None:
125
+ """Deletes a specific feedback item.
126
+
127
+ Args:
128
+ feedback_id (str): The ID of the feedback item.
129
+ """
130
+ url = f"{self.base_url}/feedbacks/{feedback_id}"
131
+ self._make_request("DELETE", url)
132
+
133
+ ####################################################################################
134
+ # Contacts API Methods #
135
+ ####################################################################################
136
+
137
+ def create_contact(self, contact: Dict[str, Any]) -> Dict[str, Any]:
138
+ """Creates a new contact item.
139
+
140
+ Args:
141
+ contact (Dict[str, Any]): The contact data to create.
142
+
143
+ Returns:
144
+ Dict[str, Any]: The created contact item.
145
+ """
146
+ url = f"{self.base_url}/crm/contacts"
147
+
148
+ # Ensure required fields are present
149
+ required_fields = [
150
+ "name", "lastname", "email", "companyId"
151
+ ]
152
+ for field in required_fields:
153
+ if field not in contact:
154
+ raise ValueError(f"Missing required field: {field}")
155
+
156
+ return self._make_request("POST", url, json=contact)
157
+
158
+ def get_contacts(self, filter) -> Dict[str, Any]:
159
+ """Retrieves a specific contact item.
160
+
161
+ Args:
162
+ contact_id (str): The ID of the contact item.
163
+ filter (Dict[str, Any]): The filter to apply to the contacts.
164
+
165
+ Returns:
166
+ Dict[str, Any]: The retrieved contact item.
167
+ """
168
+ url = f"{self.base_url}/crm/contacts"
169
+ if filter:
170
+ url = f"{url}?filter={json.dumps(filter)}"
171
+
172
+ return self._make_request("GET", url)
173
+
174
+ def update_contact(self, contact_id: str, contact: Dict[str, Any]) -> Dict[str, Any]:
175
+ """Updates a specific contact item.
176
+
177
+ Args:
178
+ contact_id (str): The ID of the contact item.
179
+ contact (Dict[str, Any]): The updated contact data.
180
+
181
+ Returns:
182
+ Dict[str, Any]: The updated contact item.
183
+ """
184
+ url = f"{self.base_url}/crm/contacts/{contact_id}"
185
+ return self._make_request("PATCH", url, json=contact)
186
+
187
+ def delete_contact(self, contact_id: str) -> None:
188
+ """Deletes a specific contact item.
189
+
190
+ Args:
191
+ contact_id (str): The ID of the contact item.
192
+ """
193
+ url = f"{self.base_url}/crm/contacts/{contact_id}"
194
+ self._make_request("DELETE", url)
195
+
196
+ ####################################################################################
197
+ # Campaigns API Methods #
198
+ ####################################################################################
199
+
200
+ def create_campaign(self, campaign: Dict[str, Any]) -> Dict[str, Any]:
201
+ """Creates a new campaign item.
202
+
203
+ Args:
204
+ campaign (Dict[str, Any]): The campaign data to create.
205
+
206
+ Returns:
207
+ Dict[str, Any]: The created campaign item.
208
+ """
209
+ url = f"{self.base_url}/campaigns"
210
+
211
+ # Ensure required fields are present
212
+ required_fields = [
213
+ "name", "companyId"
214
+ ]
215
+ for field in required_fields:
216
+ if field not in campaign:
217
+ raise ValueError(f"Missing required field: {field}")
218
+
219
+ return self._make_request("POST", url, json=campaign)
220
+
221
+ def get_campaigns(self, filter) -> Dict[str, Any]:
222
+ """Retrieves a specific campaign item.
223
+
224
+ Args:
225
+ campaign_id (str): The ID of the campaign item.
226
+ filter (Dict[str, Any]): The filter to apply to the campaigns.
227
+
228
+ Returns:
229
+ Dict[str, Any]: The retrieved campaign item.
230
+ """
231
+ url = f"{self.base_url}/campaigns"
232
+ if filter:
233
+ url = f"{url}?filter={json.dumps(filter)}"
234
+
235
+ return self._make_request("GET", url)
236
+
237
+ def create_campaign_session(self, campaign_id: str, session: Dict[str, Any]) -> Dict[str, Any]:
238
+ """Creates a new campaign session item.
239
+
240
+ Args:
241
+ campaign_id (str): The ID of the campaign.
242
+ session (Dict[str, Any]): The session data to create.
243
+
244
+ Returns:
245
+ Dict[str, Any]: The created campaign session item.
246
+ """
247
+ url = f"{self.base_url}/campaigns/{campaign_id}/session"
248
+
249
+ # Ensure required fields are present
250
+ required_fields = [
251
+ "crmContactId"
252
+ ]
253
+ for field in required_fields:
254
+ if field not in session:
255
+ raise ValueError(f"Missing required field: {field}")
256
+
257
+ if len(session.get("crmContactId")) == 0:
258
+ raise ValueError("Contact ID cannot be empty.")
259
+
260
+ return self._make_request("POST", url, json=session)
261
+
262
+ def get_campaign_sessions(self, campaign_id: str, filter) -> Dict[str, Any]:
263
+ """Retrieves a specific campaign session item.
264
+
265
+ Args:
266
+ campaign_id (str): The ID of the campaign.
267
+ filter (Dict[str, Any]): The filter to apply to the campaign sessions.
268
+
269
+ Returns:
270
+ Dict[str, Any]: The retrieved campaign session item.
271
+ """
272
+ url = f"{self.base_url}/campaigns/{campaign_id}/sessions"
273
+ if filter:
274
+ url = f"{url}?filter={json.dumps(filter)}"
275
+
276
+ return self._make_request("GET", url)
@@ -0,0 +1,87 @@
1
+ import random
2
+ import string
3
+
4
+ import pytest
5
+
6
+ from src.magicfeedback import MagicFeedbackClient
7
+
8
+ '''
9
+ def test_create_campaign(client):
10
+ """Tests creating a new campaign item."""
11
+
12
+ campaign_name = generate_random_string(10)
13
+
14
+ #
15
+ campaign_data = {
16
+ "name": campaign_name,
17
+ "companyId": "MAGICFEEDBACK_DEV_SDK"
18
+ }
19
+
20
+ response = client.create_campaign(campaign_data)
21
+
22
+ assert "id" in response
23
+ # Check if the created contact has the correct name
24
+ assert response["name"] == campaign_name
25
+
26
+ def test_list_campaign(client):
27
+ """Tests listing campaign items."""
28
+
29
+ filter = {
30
+ "where": {
31
+ "companyId": "MAGICFEEDBACK_DEV_SDK"
32
+ }
33
+ }
34
+
35
+ response = client.get_campaigns(filter)
36
+ assert len(response) > 0
37
+ '''
38
+
39
+ def test_create_campaign_session(client):
40
+ """Tests creating a new campaign session item."""
41
+
42
+ # Create a new campaign
43
+ campaign_name = generate_random_string(10)
44
+
45
+ campaign_data = {
46
+ "name": campaign_name,
47
+ "companyId": "MAGICFEEDBACK_DEV_SDK"
48
+ }
49
+
50
+ campaign = client.create_campaign(campaign_data)
51
+ assert "id" in campaign
52
+
53
+ # List only 2 contacts from the company
54
+ filter = {
55
+ "where": {
56
+ "companyId": "MAGICFEEDBACK_DEV_SDK",
57
+ "status": "ACTIVE"
58
+ },
59
+ "limit": 2
60
+ }
61
+
62
+ contacts = client.get_contacts(filter)
63
+ assert len(contacts) > 0
64
+
65
+ # Asign the contacts to the campaign
66
+ session_data = {
67
+ "crmContactId": []
68
+ }
69
+ for contact in contacts:
70
+ session_data.get("crmContactId").append(contact["id"])
71
+
72
+ response = client.create_campaign_session(campaign["id"], session_data)
73
+
74
+ @pytest.fixture
75
+ def client():
76
+ """Provides a MagicFeedbackClient instance for testing."""
77
+
78
+ client = MagicFeedbackClient('sdk_tester@magicfeedback.io', 'caracter')
79
+ return client
80
+
81
+ # Generate random name, last name and email
82
+
83
+
84
+ def generate_random_string(length):
85
+ """Generates a random string of given length."""
86
+ letters = string.ascii_letters
87
+ return ''.join(random.choice(letters) for _ in range(length))
@@ -0,0 +1,57 @@
1
+ import random
2
+ import string
3
+
4
+ import pytest
5
+
6
+ from src.magicfeedback import MagicFeedbackClient
7
+
8
+
9
+ def test_create_contact(client):
10
+ """Tests creating a new contact item."""
11
+
12
+ name = generate_random_string(5)
13
+ last_name = generate_random_string(7)
14
+ email = f"{name}.{last_name}@test.com"
15
+
16
+ #
17
+ contact_data = {
18
+ "name": name,
19
+ "lastname": last_name,
20
+ "email": email,
21
+ "companyId": "MAGICFEEDBACK_DEV_SDK"
22
+ }
23
+
24
+ response = client.create_contact(contact_data)
25
+
26
+ assert "id" in response
27
+ # Check if the created contact has the correct name
28
+ assert response["name"] == name
29
+ assert response["lastname"] == last_name
30
+ assert response["email"] == email
31
+
32
+ def test_list_contact(client):
33
+ """Tests listing contact items."""
34
+
35
+ filter = {
36
+ "where": {
37
+ "companyId": "MAGICFEEDBACK_DEV_SDK"
38
+ }
39
+ }
40
+
41
+ response = client.get_contacts(filter)
42
+ assert len(response) > 0
43
+
44
+ @pytest.fixture
45
+ def client():
46
+ """Provides a MagicFeedbackClient instance for testing."""
47
+
48
+ client = MagicFeedbackClient('sdk_tester@magicfeedback.io', 'caracter')
49
+ return client
50
+
51
+ # Generate random name, last name and email
52
+
53
+
54
+ def generate_random_string(length):
55
+ """Generates a random string of given length."""
56
+ letters = string.ascii_letters
57
+ return ''.join(random.choice(letters) for _ in range(length))
@@ -1,6 +1,8 @@
1
1
  import pytest
2
+
2
3
  from src.magicfeedback import MagicFeedbackClient
3
4
 
5
+
4
6
  def test_create_feedback(client):
5
7
  """Tests creating a new feedback item."""
6
8
 
@@ -1,131 +0,0 @@
1
- import json
2
- from typing import Any, Dict
3
-
4
- import requests
5
-
6
-
7
- class MagicFeedbackClient:
8
- """A Python SDK for interacting with the MagicFeedback API."""
9
-
10
- def __init__(self, user: str, password: str, base_url: str = "https://api.magicfeedback.io", ip_key: str = 'AIzaSyAKcR895VURSQZSN2T_RD6jX_9y5HRmH80'):
11
-
12
- self.base_url = base_url
13
- self.ip_key = ip_key
14
-
15
- self.api_key = self.get_api_key(user, password)
16
- self.headers = {"Authorization": f"Bearer {self.api_key}"}
17
-
18
- def get_api_key(self, user, password):
19
- """Obtains the API key using user and password authentication."""
20
- # TODO: Implement control to check if the token is still valid - Only for 1 hour
21
- # Call your existing function
22
- id_token = self.identity_login(user, password)
23
- return id_token
24
-
25
- def identity_login(self, user, password):
26
- """
27
- (Replace this function with your existing `identity_login` function)
28
-
29
- Performs user and password-based login using the identity toolkit API.
30
-
31
- Returns:
32
- str: The obtained ID token.
33
- """
34
- # TODO: Control in case the call is not good
35
- print("Logging in with user and password...")
36
- print("User: ", user)
37
- print("Password: ", password)
38
-
39
- options = {
40
- "method": "POST",
41
- "url": "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=" + self.ip_key,
42
- "headers": {
43
- "Content-Type": "application/javascript",
44
- },
45
- "data": json.dumps({
46
- "email": user,
47
- "password": password,
48
- "returnSecureToken": True
49
- })
50
- }
51
-
52
- response = requests.post(
53
- options["url"], headers=options["headers"], data=options["data"])
54
- data = json.loads(response.text)
55
- return data["idToken"]
56
-
57
- def _make_request(
58
- self, method: str, url: str, json: Dict[str, Any] = None
59
- ) -> Dict[str, Any]:
60
- """Makes a request to the MagicFeedback API."""
61
- # TODO: Control token expiration
62
- response = requests.request(
63
- method, url, headers=self.headers, json=json)
64
- response.raise_for_status() # Raise exception for non-2xx status codes
65
- # TODO: Control the status of the call
66
- print("Status code: ", response.status_code)
67
- print("Response: ", response.json())
68
-
69
- return response.json()
70
-
71
- ####################################################################################
72
- # Feedback API Methods #
73
- ####################################################################################
74
-
75
- def create_feedback(self, feedback: Dict[str, Any]) -> Dict[str, Any]:
76
- """Creates a new feedback item.
77
-
78
- Args:
79
- feedback (Dict[str, Any]): The feedback data to create.
80
-
81
- Returns:
82
- Dict[str, Any]: The created feedback item.
83
- """
84
- url = f"{self.base_url}/feedbacks"
85
-
86
- # Ensure required fields are present
87
- required_fields = [
88
- "name", "type", "identity",
89
- "integrationId", "companyId",
90
- "productId"
91
- ]
92
- for field in required_fields:
93
- if field not in feedback:
94
- raise ValueError(f"Missing required field: {field}")
95
-
96
- return self._make_request("POST", url, json=feedback)
97
-
98
- # Add other API methods as needed
99
- def get_feedback(self, feedback_id: str) -> Dict[str, Any]:
100
- """Retrieves a specific feedback item.
101
-
102
- Args:
103
- feedback_id (str): The ID of the feedback item.
104
-
105
- Returns:
106
- Dict[str, Any]: The retrieved feedback item.
107
- """
108
- url = f"{self.base_url}/feedbacks/{feedback_id}"
109
- return self._make_request("GET", url)
110
-
111
- def update_feedback(self, feedback_id: str, feedback: Dict[str, Any]) -> Dict[str, Any]:
112
- """Updates a specific feedback item.
113
-
114
- Args:
115
- feedback_id (str): The ID of the feedback item.
116
- feedback (Dict[str, Any]): The updated feedback data.
117
-
118
- Returns:
119
- Dict[str, Any]: The updated feedback item.
120
- """
121
- url = f"{self.base_url}/feedbacks/{feedback_id}"
122
- return self._make_request("PUT", url, json=feedback)
123
-
124
- def delete_feedback(self, feedback_id: str) -> None:
125
- """Deletes a specific feedback item.
126
-
127
- Args:
128
- feedback_id (str): The ID of the feedback item.
129
- """
130
- url = f"{self.base_url}/feedbacks/{feedback_id}"
131
- self._make_request("DELETE", url)
File without changes
File without changes
File without changes