dhisana 0.0.1.dev238__py3-none-any.whl → 0.0.1.dev240__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.
@@ -0,0 +1,123 @@
1
+ import os
2
+ import aiohttp
3
+ import logging
4
+ from typing import List, Dict, Any, Optional
5
+ from dhisana.utils.assistant_tool_tag import assistant_tool
6
+
7
+ logging.basicConfig(level=logging.INFO)
8
+ logger = logging.getLogger(__name__)
9
+
10
+ base_url = 'https://api.mailreach.co/api/v1'
11
+
12
+
13
+ def get_mailreach_api_key(tool_config: Optional[List[Dict]] = None) -> str:
14
+ """
15
+ Retrieves the MailReach API key from the provided tool configuration or environment variables.
16
+
17
+ Args:
18
+ tool_config (list): A list of dictionaries containing the tool configuration.
19
+ Each dictionary should have a "name" key and a "configuration" key,
20
+ where "configuration" is a list of dictionaries containing "name" and "value" keys.
21
+
22
+ Returns:
23
+ str: The MailReach API key.
24
+
25
+ Raises:
26
+ ValueError: If the MailReach integration has not been configured.
27
+ """
28
+ api_key = None
29
+
30
+ if tool_config:
31
+ mailreach_config = next(
32
+ (item for item in tool_config if item.get("name") == "mailreach"), None
33
+ )
34
+ if mailreach_config:
35
+ config_map = {
36
+ item["name"]: item["value"]
37
+ for item in mailreach_config.get("configuration", [])
38
+ if item
39
+ }
40
+ api_key = config_map.get("apiKey")
41
+
42
+ api_key = api_key or os.getenv("MAILREACH_API_KEY")
43
+
44
+ if not api_key:
45
+ raise ValueError(
46
+ "MailReach integration is not configured. Please configure the connection to MailReach in Integrations."
47
+ )
48
+
49
+ return api_key
50
+
51
+
52
+ def get_mailreach_headers(tool_config: Optional[List[Dict]] = None) -> Dict[str, str]:
53
+ """
54
+ Get the headers required for MailReach API requests.
55
+
56
+ Args:
57
+ tool_config (list): Optional tool configuration containing API credentials.
58
+
59
+ Returns:
60
+ Dict[str, str]: Headers dictionary with x-api-key and Content-Type.
61
+ """
62
+ api_key = get_mailreach_api_key(tool_config)
63
+ headers = {
64
+ "x-api-key": api_key,
65
+ "Content-Type": "application/json"
66
+ }
67
+ return headers
68
+
69
+
70
+ async def _handle_mailreach_response(response: aiohttp.ClientResponse) -> Any:
71
+ """
72
+ Handle MailReach API responses consistently.
73
+
74
+ Args:
75
+ response: The aiohttp ClientResponse object.
76
+
77
+ Returns:
78
+ The JSON response data.
79
+
80
+ Raises:
81
+ aiohttp.ClientResponseError: For rate limits or other errors.
82
+ """
83
+ if response.status == 200:
84
+ return await response.json()
85
+ elif response.status == 429:
86
+ raise aiohttp.ClientResponseError(
87
+ request_info=response.request_info,
88
+ history=response.history,
89
+ status=response.status,
90
+ message="Rate limit exceeded",
91
+ headers=response.headers
92
+ )
93
+ else:
94
+ error_message = await response.text()
95
+ logger.error(f"MailReach API Error {response.status}: {error_message}")
96
+ response.raise_for_status()
97
+
98
+
99
+ @assistant_tool
100
+ async def ping_mailreach(
101
+ tool_config: Optional[List[Dict]] = None
102
+ ) -> Dict[str, Any]:
103
+ """
104
+ Ping the MailReach API to verify connectivity and authentication.
105
+
106
+ This is a simple endpoint to test if your API key is valid and the service is accessible.
107
+
108
+ Args:
109
+ tool_config (list): Optional tool configuration containing API credentials.
110
+
111
+ Returns:
112
+ Dict[str, Any]: Response from the ping endpoint, typically containing a success message.
113
+ """
114
+ url = f"{base_url}/ping"
115
+ headers = get_mailreach_headers(tool_config)
116
+
117
+ logger.info("Pinging MailReach API...")
118
+
119
+ async with aiohttp.ClientSession() as session:
120
+ async with session.get(url, headers=headers) as response:
121
+ result = await _handle_mailreach_response(response)
122
+ logger.info("MailReach ping successful")
123
+ return result
@@ -483,6 +483,31 @@ async def test_sendgrid(api_key: str) -> Dict[str, Any]:
483
483
  return {"success": False, "status_code": 0, "error_message": str(e)}
484
484
 
485
485
 
486
+ async def test_mailreach(api_key: str) -> Dict[str, Any]:
487
+ """
488
+ Basic MailReach connectivity check using the Ping endpoint.
489
+
490
+ Uses the /v1/ping endpoint to verify API key validity and service availability.
491
+ Reference: https://docs.mailreach.co/reference/getv1ping
492
+ """
493
+ url = "https://api.mailreach.co/api/v1/ping"
494
+ headers = {"x-api-key": api_key}
495
+ try:
496
+ async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=10)) as session:
497
+ async with session.get(url, headers=headers) as response:
498
+ status = response.status
499
+ data = await safe_json(response)
500
+ if status != 200:
501
+ msg = None
502
+ if data and isinstance(data, dict):
503
+ msg = data.get("message") or data.get("error")
504
+ return {"success": False, "status_code": status, "error_message": msg or f"MailReach non-200: {status}"}
505
+ return {"success": True, "status_code": status, "error_message": None}
506
+ except Exception as e:
507
+ logger.error(f"MailReach test failed: {e}")
508
+ return {"success": False, "status_code": 0, "error_message": str(e)}
509
+
510
+
486
511
  async def test_samgov(api_key: str) -> Dict[str, Any]:
487
512
  """Test SAM.gov connectivity by fetching a single opportunity."""
488
513
 
@@ -1646,6 +1671,49 @@ async def test_scarf(api_key: str) -> Dict[str, Any]:
1646
1671
  return {"success": False, "status_code": 0, "error_message": str(exc)}
1647
1672
 
1648
1673
 
1674
+ async def test_theorg(api_key: str) -> Dict[str, Any]:
1675
+ """Validate The Org API key by calling the Usage endpoint."""
1676
+ url = "https://api.theorg.com/v1.1/usage"
1677
+ headers = {
1678
+ "X-Api-Key": api_key,
1679
+ "Accept": "application/json",
1680
+ }
1681
+
1682
+ try:
1683
+ timeout = aiohttp.ClientTimeout(total=10)
1684
+ async with aiohttp.ClientSession(timeout=timeout) as session:
1685
+ async with session.get(url, headers=headers) as response:
1686
+ status = response.status
1687
+ data = await safe_json(response)
1688
+
1689
+ if status == 200:
1690
+ payload = data if isinstance(data, dict) else None
1691
+ usage = payload.get("data") if payload else None
1692
+ if isinstance(usage, dict):
1693
+ return {"success": True, "status_code": status, "error_message": None}
1694
+ return {
1695
+ "success": False,
1696
+ "status_code": status,
1697
+ "error_message": "The Org usage endpoint returned an unexpected payload.",
1698
+ }
1699
+
1700
+ message = None
1701
+ if isinstance(data, dict):
1702
+ message = (
1703
+ data.get("message")
1704
+ or data.get("error")
1705
+ or data.get("detail")
1706
+ )
1707
+ return {
1708
+ "success": False,
1709
+ "status_code": status,
1710
+ "error_message": message or f"The Org responded with {status}",
1711
+ }
1712
+ except Exception as exc:
1713
+ logger.error(f"The Org connectivity test failed: {exc}")
1714
+ return {"success": False, "status_code": 0, "error_message": str(exc)}
1715
+
1716
+
1649
1717
  ###############################################################################
1650
1718
  # DATAGMA CONNECTIVITY
1651
1719
  ###############################################################################
@@ -1739,12 +1807,14 @@ async def test_connectivity(tool_config: List[Dict[str, Any]]) -> Dict[str, Dict
1739
1807
  "nooks": test_nooks,
1740
1808
  "commonRoom": test_commonroom,
1741
1809
  "scarf": test_scarf,
1810
+ "theorg": test_theorg,
1742
1811
  "salesforce": test_salesforce,
1743
1812
  "clay": test_clay,
1744
1813
  "posthog": test_posthog,
1745
1814
  "mcpServer": test_mcp_server,
1746
1815
  "slack": test_slack,
1747
1816
  "mailgun": test_mailgun,
1817
+ "mailreach": test_mailreach,
1748
1818
  "sendgrid": test_sendgrid,
1749
1819
  "samgov": test_samgov,
1750
1820
  "scraperapi": test_scraperapi,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dhisana
3
- Version: 0.0.1.dev238
3
+ Version: 0.0.1.dev240
4
4
  Summary: A Python SDK for Dhisana AI Platform
5
5
  Home-page: https://github.com/dhisana-ai/dhisana-python-sdk
6
6
  Author: Admin
@@ -54,6 +54,7 @@ dhisana/utils/instantly_tools.py,sha256=hhqjDPyLE6o0dzzuvryszbK3ipnoGU2eBm6NlsUG
54
54
  dhisana/utils/linkedin_crawler.py,sha256=6fMQTY5lTw2kc65SFHgOAM6YfezAS0Yhg-jkiX8LGHo,6533
55
55
  dhisana/utils/lusha_tools.py,sha256=MdiWlxBBjSNpSKz8rhNOyLPtbeh-YWHgGiUq54vN_gM,12734
56
56
  dhisana/utils/mailgun_tools.py,sha256=qUD-jFMZpmkkkKtyihVSe9tgFzYe-UiiBDHQKtsLq0M,5284
57
+ dhisana/utils/mailreach_tools.py,sha256=uJ_gIcg8qrj5-k3jnYYhpwLVnQncoA1swzr5Jfkc1JU,3864
57
58
  dhisana/utils/microsoft365_tools.py,sha256=aNIUBBz56HhvnEd0ZMy5EGAtsXcBJ_VOMO5Yy4dyojQ,18289
58
59
  dhisana/utils/openai_assistant_and_file_utils.py,sha256=-eyPcxFvtS-DDtYQGle1SU6C6CuxjulVIojFy27HeWc,8957
59
60
  dhisana/utils/openai_helpers.py,sha256=ZK9S5-jcLCpiiD6XBLkCqYcNz-AGYmO9xh4e2H-FDLo,40155
@@ -79,7 +80,7 @@ dhisana/utils/serperdev_google_jobs.py,sha256=m5_2f_5y79FOFZz1A_go6m0hIUfbbAoZ0Y
79
80
  dhisana/utils/serperdev_local_business.py,sha256=JoZfTg58Hojv61cyuwA2lcnPdLT1lawnWaBNrUYWnuQ,6447
80
81
  dhisana/utils/serperdev_search.py,sha256=_iBKIfHMq4gFv5StYz58eArriygoi1zW6VnLlux8vto,9363
81
82
  dhisana/utils/smtp_email_tools.py,sha256=_1FoN6e-rgkjAKnCVym_IvihJFKz_dOo-43iM6CVqhA,21855
82
- dhisana/utils/test_connect.py,sha256=aQjPIKevMF_c-wd4Te2UtPpaY-dEa9PVp6MsNCjQ7q8,83667
83
+ dhisana/utils/test_connect.py,sha256=pYR1Ki6WKx-vAhLJxQ6At627xfOnlQeVRjnW7FBdGKM,86702
83
84
  dhisana/utils/trasform_json.py,sha256=7V72XNDpuxUX0GHN5D83z4anj_gIf5zabaHeQm7b1_E,6979
84
85
  dhisana/utils/web_download_parse_tools.py,sha256=ouXwH7CmjcRjoBfP5BWat86MvcGO-8rLCmWQe_eZKjc,7810
85
86
  dhisana/utils/workflow_code_model.py,sha256=YPWse5vBb3O6Km2PvKh1Q3AB8qBkzLt1CrR5xOL9Mro,99
@@ -93,8 +94,8 @@ dhisana/workflow/agent.py,sha256=esv7_i_XuMkV2j1nz_UlsHov_m6X5WZZiZm_tG4OBHU,565
93
94
  dhisana/workflow/flow.py,sha256=xWE3qQbM7j2B3FH8XnY3zOL_QXX4LbTW4ArndnEYJE0,1638
94
95
  dhisana/workflow/task.py,sha256=HlWz9mtrwLYByoSnePOemBUBrMEcj7KbgNjEE1oF5wo,1830
95
96
  dhisana/workflow/test.py,sha256=E7lRnXK0PguTNzyasHytLzTJdkqIPxG5_4qk4hMEeKc,3399
96
- dhisana-0.0.1.dev238.dist-info/METADATA,sha256=bCqE8Mcg_kxsYFx8NgwhaQufzBiFGNTnBAUELC0fiEg,1190
97
- dhisana-0.0.1.dev238.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
98
- dhisana-0.0.1.dev238.dist-info/entry_points.txt,sha256=jujxteZmNI9EkEaK-pOCoWuBujU8TCevdkfl9ZcKHek,49
99
- dhisana-0.0.1.dev238.dist-info/top_level.txt,sha256=NETTHt6YifG_P7XtRHbQiXZlgSFk9Qh9aR-ng1XTf4s,8
100
- dhisana-0.0.1.dev238.dist-info/RECORD,,
97
+ dhisana-0.0.1.dev240.dist-info/METADATA,sha256=jRWykbajxwI0der7CKSyvAojMJu0xtuGQotostyySAM,1190
98
+ dhisana-0.0.1.dev240.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
99
+ dhisana-0.0.1.dev240.dist-info/entry_points.txt,sha256=jujxteZmNI9EkEaK-pOCoWuBujU8TCevdkfl9ZcKHek,49
100
+ dhisana-0.0.1.dev240.dist-info/top_level.txt,sha256=NETTHt6YifG_P7XtRHbQiXZlgSFk9Qh9aR-ng1XTf4s,8
101
+ dhisana-0.0.1.dev240.dist-info/RECORD,,