Added cli client.
This commit is contained in:
parent
47745e7fd5
commit
9cda468357
102
alert_clients/alarm_api_client.py
Normal file
102
alert_clients/alarm_api_client.py
Normal file
@ -0,0 +1,102 @@
|
||||
import requests
|
||||
import json
|
||||
|
||||
|
||||
class AlarmApiClient:
|
||||
def __init__(self, base_url: str):
|
||||
"""
|
||||
Initialize the Alarm API client.
|
||||
:param base_url: Base URL of the Alarm API server (e.g., 'http://localhost:8000')
|
||||
"""
|
||||
self.base_url = base_url.rstrip("/")
|
||||
|
||||
def _handle_response(self, response: requests.Response) -> dict:
|
||||
"""
|
||||
Handle API responses, raising exceptions for errors.
|
||||
:param response: The HTTP response object.
|
||||
:return: Parsed JSON data if the response is successful.
|
||||
"""
|
||||
try:
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
except requests.HTTPError as e:
|
||||
raise Exception(f"HTTP error {response.status_code}: {response.text}") from e
|
||||
except json.JSONDecodeError:
|
||||
raise Exception("Invalid JSON response")
|
||||
|
||||
def get_alarms(self) -> list:
|
||||
"""
|
||||
Retrieve all alarms from the API.
|
||||
:return: List of alarm configurations.
|
||||
"""
|
||||
response = requests.get(f"{self.base_url}/")
|
||||
return self._handle_response(response)["data"]
|
||||
|
||||
def create_alarm(self, alarm_data: dict) -> int:
|
||||
"""
|
||||
Create a new alarm.
|
||||
:param alarm_data: Dictionary containing alarm configuration.
|
||||
:return: ID of the newly created alarm.
|
||||
"""
|
||||
response = requests.post(f"{self.base_url}/", json=alarm_data)
|
||||
return self._handle_response(response)["data"]["id"]
|
||||
|
||||
def update_alarm(self, alarm_id: int, alarm_data: dict) -> bool:
|
||||
"""
|
||||
Update an existing alarm.
|
||||
:param alarm_id: ID of the alarm to update.
|
||||
:param alarm_data: Updated alarm configuration.
|
||||
:return: True if the update was successful.
|
||||
"""
|
||||
alarm_data["id"] = alarm_id
|
||||
response = requests.put(f"{self.base_url}/", json=alarm_data)
|
||||
return "message" in self._handle_response(response)
|
||||
|
||||
def delete_alarm(self, alarm_id: int) -> bool:
|
||||
"""
|
||||
Delete an alarm by its ID.
|
||||
:param alarm_id: ID of the alarm to delete.
|
||||
:return: True if the deletion was successful.
|
||||
"""
|
||||
response = requests.delete(f"{self.base_url}/", json={"id": alarm_id})
|
||||
return "message" in self._handle_response(response)
|
||||
|
||||
|
||||
# Example Usage
|
||||
#if __name__ == "__main__":
|
||||
# client = AlarmApiClient("http://localhost:8000")
|
||||
#
|
||||
# # Create a new alarm
|
||||
# new_alarm = {
|
||||
# "name": "Morning Alarm",
|
||||
# "time": "07:00:00",
|
||||
# "repeat_rule": {
|
||||
# "type": "daily"
|
||||
# },
|
||||
# "enabled": True,
|
||||
# "snooze": {
|
||||
# "enabled": True,
|
||||
# "duration": 10,
|
||||
# "max_count": 3
|
||||
# },
|
||||
# "metadata": {
|
||||
# "volume": 80,
|
||||
# "notes": "Wake up alarm"
|
||||
# },
|
||||
# }
|
||||
# alarm_id = client.create_alarm(new_alarm)
|
||||
# print(f"Created alarm with ID: {alarm_id}")
|
||||
#
|
||||
# # Get all alarms
|
||||
# alarms = client.get_alarms()
|
||||
# print(f"Current alarms: {alarms}")
|
||||
#
|
||||
# # Update the alarm
|
||||
# updated_alarm = new_alarm.copy()
|
||||
# updated_alarm["time"] = "07:30:00"
|
||||
# client.update_alarm(alarm_id, updated_alarm)
|
||||
# print(f"Updated alarm ID {alarm_id}")
|
||||
#
|
||||
# # Delete the alarm
|
||||
# client.delete_alarm(alarm_id)
|
||||
# print(f"Deleted alarm ID {alarm_id}")
|
151
alert_clients/alarm_client_cli.py
Executable file
151
alert_clients/alarm_client_cli.py
Executable file
@ -0,0 +1,151 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from alarm_api_client import AlarmApiClient
|
||||
|
||||
|
||||
CONFIG_FILE = Path.home() / ".alarms.json"
|
||||
|
||||
|
||||
def load_config() -> dict:
|
||||
"""Load configuration from the config file."""
|
||||
if CONFIG_FILE.exists():
|
||||
with CONFIG_FILE.open() as f:
|
||||
return json.load(f)
|
||||
return {}
|
||||
|
||||
|
||||
def save_config(config: dict) -> None:
|
||||
"""Save configuration to the config file."""
|
||||
with CONFIG_FILE.open("w") as f:
|
||||
json.dump(config, f, indent=4)
|
||||
print(f"Configuration saved to {CONFIG_FILE}")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="CLI for interacting with the Alarm API")
|
||||
parser.add_argument("--host", type=str, help="Alarm API host URL (overrides saved config)")
|
||||
parser.add_argument("--save-config", action="store_true", help="Save the provided host URL to the config file")
|
||||
|
||||
subparsers = parser.add_subparsers(title="Commands", dest="command")
|
||||
|
||||
# Create alarm
|
||||
create_parser = subparsers.add_parser("create", help="Create a new alarm")
|
||||
create_parser.add_argument("--name", required=False, help="Name of the alarm")
|
||||
create_parser.add_argument("--time", required=False, help="Alarm time in HH:MM:SS format")
|
||||
create_parser.add_argument("--repeat-type", choices=["daily", "weekly", "once"], help="Repeat type")
|
||||
create_parser.add_argument("--days", nargs="*", help="Days of the week for weekly repeat (e.g., monday tuesday)")
|
||||
create_parser.add_argument("--enabled", type=bool, default=True, help="Enable or disable the alarm")
|
||||
create_parser.add_argument("--snooze-duration", type=int, default=10, help="Snooze duration in minutes")
|
||||
create_parser.add_argument("--snooze-count", type=int, default=3, help="Maximum snooze count")
|
||||
create_parser.add_argument("--volume", type=int, default=80, help="Volume level (0-100)")
|
||||
create_parser.add_argument("--notes", type=str, default="", help="Notes for the alarm")
|
||||
create_parser.add_argument("--file", type=str, help="Path to the alarm sound file")
|
||||
create_parser.add_argument("--from-file", type=str, help="Path to JSON file containing alarm configuration")
|
||||
|
||||
# Get alarms
|
||||
subparsers.add_parser("list", help="List all alarms")
|
||||
|
||||
# Update alarm
|
||||
update_parser = subparsers.add_parser("update", help="Update an existing alarm")
|
||||
update_parser.add_argument("--id", type=int, required=True, help="ID of the alarm to update")
|
||||
update_parser.add_argument("--name", help="Updated name of the alarm")
|
||||
update_parser.add_argument("--time", help="Updated time in HH:MM:SS format")
|
||||
update_parser.add_argument("--repeat-type", choices=["daily", "weekly"], help="Updated repeat type")
|
||||
update_parser.add_argument("--days", nargs="*", help="Updated days of the week for weekly repeat")
|
||||
update_parser.add_argument("--enabled", type=bool, help="Enable or disable the alarm")
|
||||
update_parser.add_argument("--snooze-duration", type=int, help="Updated snooze duration in minutes")
|
||||
update_parser.add_argument("--snooze-count", type=int, help="Updated maximum snooze count")
|
||||
update_parser.add_argument("--volume", type=int, help="Updated volume level (0-100)")
|
||||
update_parser.add_argument("--notes", type=str, help="Updated notes for the alarm")
|
||||
update_parser.add_argument("--file", type=str, help="Updated path to the alarm sound file")
|
||||
|
||||
# Delete alarm
|
||||
delete_parser = subparsers.add_parser("delete", help="Delete an alarm")
|
||||
delete_parser.add_argument("--id", type=int, required=True, help="ID of the alarm to delete")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Load saved config
|
||||
config = load_config()
|
||||
host = args.host or config.get("host", "http://localhost:8000")
|
||||
|
||||
if args.save_config:
|
||||
config["host"] = host
|
||||
save_config(config)
|
||||
|
||||
client = AlarmApiClient(host)
|
||||
|
||||
try:
|
||||
if args.command == "create":
|
||||
if args.from_file:
|
||||
with open(args.from_file, "r") as f:
|
||||
alarm_data = json.load(f)
|
||||
print(f"Creating alarm from file: {args.from_file}")
|
||||
else:
|
||||
repeat_rule = {"type": args.repeat_type}
|
||||
if args.repeat_type == "weekly":
|
||||
repeat_rule["days_of_week"] = args.days or []
|
||||
alarm_data = {
|
||||
"name": args.name,
|
||||
"time": args.time,
|
||||
"repeat_rule": repeat_rule,
|
||||
"enabled": args.enabled,
|
||||
"snooze": {"enabled": True, "duration": args.snooze_duration, "max_count": args.snooze_count},
|
||||
"metadata": {"volume": args.volume, "notes": args.notes},
|
||||
}
|
||||
if args.file:
|
||||
alarm_data["file_to_play"] = args.file
|
||||
alarm_id = client.create_alarm(alarm_data)
|
||||
print(f"Alarm created with ID: {alarm_id}")
|
||||
|
||||
elif args.command == "list":
|
||||
alarms = client.get_alarms()
|
||||
if not alarms:
|
||||
print("No alarms found.")
|
||||
else:
|
||||
for alarm in alarms:
|
||||
print(json.dumps(alarm, indent=4))
|
||||
|
||||
elif args.command == "update":
|
||||
alarm_data = {}
|
||||
if args.name:
|
||||
alarm_data["name"] = args.name
|
||||
if args.time:
|
||||
alarm_data["time"] = args.time
|
||||
if args.repeat_type:
|
||||
alarm_data["repeat_rule"] = {"type": args.repeat_type}
|
||||
if args.repeat_type == "weekly" and args.days:
|
||||
alarm_data["repeat_rule"]["days_of_week"] = args.days
|
||||
if args.enabled is not None:
|
||||
alarm_data["enabled"] = args.enabled
|
||||
if args.snooze_duration:
|
||||
alarm_data.setdefault("snooze", {})["duration"] = args.snooze_duration
|
||||
if args.snooze_count:
|
||||
alarm_data.setdefault("snooze", {})["max_count"] = args.snooze_count
|
||||
if args.volume:
|
||||
alarm_data.setdefault("metadata", {})["volume"] = args.volume
|
||||
if args.notes:
|
||||
alarm_data.setdefault("metadata", {})["notes"] = args.notes
|
||||
if args.file:
|
||||
alarm_data["file_to_play"] = args.file
|
||||
|
||||
if client.update_alarm(args.id, alarm_data):
|
||||
print(f"Alarm ID {args.id} updated successfully.")
|
||||
|
||||
elif args.command == "delete":
|
||||
if client.delete_alarm(args.id):
|
||||
print(f"Alarm ID {args.id} deleted successfully.")
|
||||
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
x
Reference in New Issue
Block a user