Skip to content

Commit 3289cc4

Browse files
committed
Adding the integration commands
1 parent 57f5e8e commit 3289cc4

4 files changed

Lines changed: 146 additions & 7 deletions

File tree

api.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,36 @@ def delete_broadcast(self, broadcast_id: str) -> Dict[str, Any]:
216216
response.raise_for_status()
217217
return response.json() if response.content else {"message": "Broadcast deleted successfully"}
218218

219+
# INTEGRATIONS
220+
# ============
221+
def list_integrations(self, limit: int = 10, offset: int = 0, search: Optional[str] = None, enabled: Optional[bool] = None) -> Dict[str, Any]:
222+
"""List all integrations in PagerTree."""
223+
params = {k: v for k, v in {"limit": limit, "offset": offset, "q": search, "enabled": enabled}.items() if v is not None}
224+
response = self.session.get(f"{self.base_url}/integrations", params=params)
225+
response.raise_for_status()
226+
data = response.json()
227+
return {
228+
"data": data.get("data", []),
229+
"total": data.get("total_count", 0),
230+
"has_more": data.get("has_more", False),
231+
"limit": limit,
232+
"offset": offset
233+
}
234+
235+
def show_integration(self, integration_id: str) -> Dict[str, Any]:
236+
"""Fetch a single integration by ID from PagerTree."""
237+
response = self.session.get(f"{self.base_url}/integrations/{integration_id}")
238+
response.raise_for_status()
239+
return response.json()
240+
241+
def update_integration(self, integration_id: str, enabled: Optional[bool] = None) -> Dict[str, Any]:
242+
"""Enable an integration in PagerTree."""
243+
payload = {"enabled": enabled}
244+
payload = {k: v for k, v in payload.items() if v is not None}
245+
response = self.session.put(f"{self.base_url}/integrations/{integration_id}", json=payload)
246+
response.raise_for_status()
247+
return response.json()
248+
219249
# TEAMS
220250
# ======
221251

commands/integrations.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import click
2+
import json
3+
from utils import display_paginated_results, handle_api_error, format_item_details
4+
5+
@click.group()
6+
def integrations():
7+
"""Commands for managing PagerTree integrations."""
8+
pass
9+
10+
@integrations.command(name="show")
11+
@click.argument("integration_id", required=True)
12+
@click.pass_context
13+
def show_integration_cmd(ctx, integration_id):
14+
"""Show details of a specific integration in PagerTree."""
15+
try:
16+
client = ctx.obj.client # Get PagerTreeClient from context
17+
integration = client.show_integration(integration_id)
18+
fields = {
19+
"id": "ID",
20+
"name": "Name",
21+
"integration_type.name": "Type",
22+
"enabled": "Enabled",
23+
"created_at": "Created At",
24+
"updated_at": "Updated At"
25+
}
26+
format_item_details(integration, fields)
27+
except Exception as e:
28+
handle_api_error(e, "showing integration")
29+
30+
@integrations.command(name="list")
31+
@click.option("--limit", default=10, type=click.IntRange(1, 100), help="Number of integrations per page")
32+
@click.option("--offset", default=0, type=click.IntRange(0), help="Starting point for pagination")
33+
@click.option("--search", help="Search for integrations by name or type")
34+
@click.option("--enabled", is_flag=True, help="Filter for enabled integrations", default=None)
35+
@click.option("--disabled", is_flag=True, help="Filter for disabled integrations")
36+
@click.pass_context
37+
def list_integrations_cmd(ctx, limit, offset, search, enabled, disabled):
38+
"""List integrations in PagerTree with pagination."""
39+
try:
40+
# Ensure --enabled and --disabled are mutually exclusive
41+
if enabled and disabled:
42+
click.echo("Error: --enabled and --disabled cannot be used together.")
43+
return
44+
45+
# Set enabled parameter: True for --enabled, False for --disabled, None if neither
46+
enabled_param = 1 if enabled else 0 if disabled else None
47+
48+
client = ctx.obj.client # Get PagerTreeClient from context
49+
logger = ctx.obj.logger # Get logger from context
50+
logger.debug(f"Listing integrations with limit={limit}, offset={offset}, search={search}, enabled={enabled_param}")
51+
result = client.list_integrations(limit=limit, offset=offset, search=search, enabled=enabled_param)
52+
logger.debug(f"Full response: {json.dumps(result, indent=2)}")
53+
integrations_list = result["data"]
54+
total = result["total"]
55+
# Prepare table data
56+
headers = ["ID", "Name", "Type", "Enabled"]
57+
table_data = [[integration.get("id"), integration.get("name"), integration.get("integration_type").get("name"), integration.get("enabled")] for integration in integrations_list]
58+
display_paginated_results(integrations_list, total, limit, offset, "integration", headers, table_data)
59+
except Exception as e:
60+
logger.error(f"Error listing integrations: {str(e)}")
61+
handle_api_error(e, action="listing integrations")
62+
63+
@integrations.command(name="enable")
64+
@click.argument("integration_id", required=True)
65+
@click.pass_context
66+
def enable_integration_cmd(ctx, integration_id):
67+
"""Enable an integration in PagerTree."""
68+
try:
69+
client = ctx.obj.client # Get PagerTreeClient from context
70+
result = client.update_integration(integration_id, enabled=True)
71+
click.echo(f"Integration enabled successfully: {result.get('id')}")
72+
except Exception as e:
73+
handle_api_error(e, action="enabling integration")
74+
75+
@integrations.command(name="disable")
76+
@click.argument("integration_id", required=True)
77+
@click.pass_context
78+
def disable_integration_cmd(ctx, integration_id):
79+
"""Disable an integration in PagerTree."""
80+
try:
81+
client = ctx.obj.client # Get PagerTreeClient from context
82+
result = client.update_integration(integration_id, enabled=False)
83+
click.echo(f"Integration disabled successfully: {result.get('id')}")
84+
except Exception as e:
85+
handle_api_error(e, action="disabling integration")

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ certifi==2025.1.31
33
charset-normalizer==3.4.1
44
click==8.1.8
55
idna==3.10
6+
jsonpath-ng==1.7.0
67
packaging==24.2
8+
ply==3.11
79
pyinstaller==6.12.0
810
pyinstaller-hooks-contrib==2025.2
911
python-dotenv==1.1.0

utils.py

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import click
22
import requests
3+
from typing import Dict, Any
4+
from jsonpath_ng import parse
5+
from jsonpath_ng.exceptions import JsonPathParserError, JsonPathLexerError
36
from tabulate import tabulate
47

58
def handle_api_error(e, action="performing action"):
@@ -23,14 +26,33 @@ def display_paginated_results(items, total, limit, offset, item_type="item", tab
2326
if offset + limit < total:
2427
click.echo(f"More {item_type}s available. Use --offset {offset + limit} to see next page.")
2528

26-
def format_item_details(item, fields):
27-
"""Format and display item details as a table using tabulate."""
29+
def format_item_details(item: Dict[str, Any], fields: Dict[str, str]) -> None:
30+
"""Format and display item details as a table using tabulate, supporting JSON path notation."""
2831
# Prepare table data: each row is [Display Name, Value]
29-
table_data = [
30-
[display_name, item.get(field_name, "N/A")]
31-
for field_name, display_name in fields.items()
32-
]
32+
table_data = []
33+
for field_path, display_name in fields.items():
34+
try:
35+
# Try to parse the field_path as a JSON path
36+
jsonpath_expr = parse(field_path)
37+
matches = jsonpath_expr.find(item)
38+
value = matches[0].value if matches else "N/A"
39+
except (JsonPathParserError, JsonPathLexerError, IndexError, KeyError):
40+
# Fallback to direct dictionary access for simple field names
41+
value = item.get(field_path, "N/A")
42+
43+
# Format specific types for better readability
44+
if isinstance(value, bool):
45+
value = "Yes" if value else "No"
46+
elif isinstance(value, list):
47+
value = ", ".join(str(v) for v in value) if value else "None"
48+
elif isinstance(value, dict):
49+
value = str(value) # Convert dict to string for simplicity
50+
elif value is None:
51+
value = "N/A"
52+
53+
table_data.append([display_name, value])
54+
3355
# Define table headers
3456
headers = ["Field", "Value"]
35-
# Display the table using tabulate with github format
57+
# Display the table using tabulate with simple format
3658
click.echo(tabulate(table_data, headers=headers, tablefmt="simple", maxcolwidths=[None, 50]))

0 commit comments

Comments
 (0)