Coverage for src/edwh_uptime_plugin/uptime_plugin.py: 0%
113 statements
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-18 16:57 +0100
« prev ^ index » next coverage.py v7.4.0, created at 2024-01-18 16:57 +0100
1import json
2from typing import Optional
4import edwh
5from invoke import Context, task
7from .uptimerobot import MonitorType, UptimeRobotMonitor, uptime_robot
10@task()
11def status(_: Context, url: str) -> None:
12 """
13 Show a specific monitor by (partial) url or label.
15 :param url: required positional argument of the URL to show the status for
16 """
17 monitors = uptime_robot.get_monitors(url)
18 if not monitors:
19 print("No monitor found!")
20 return
22 for monitor in monitors:
23 print(f"- {monitor['url']}:", uptime_robot.format_status(monitor["status"]))
26@task(name="monitors")
27def monitors_verbose(_: Context, search: str = "") -> None:
28 """
29 Show all monitors full data as dict.
30 You can optionally add a search term, which will look in the URL and label.
32 :param search: (partial) URL or monitor name to filter by
33 """
34 print(json.dumps(uptime_robot.get_monitors(search), indent=2))
37@task(name="list")
38def list_statuses(_: Context, search: str = "") -> None:
39 """
40 Show the status for each monitor.
42 :param search: (partial) URL or monitor name to filter by
43 """
44 for monitor in uptime_robot.get_monitors(search):
45 print(f"- {monitor['url']}:", uptime_robot.format_status(monitor["status"]))
48@task()
49def up(_: Context, strict: bool = False) -> None:
50 """
51 List monitors that are up (probably).
53 :param strict: If strict is True, only status 2 is allowed
54 """
55 min_status = 2 if strict else 0
56 max_status = 3
58 monitors = uptime_robot.get_monitors()
59 monitors = [_ for _ in monitors if min_status <= _["status"] < max_status]
61 for monitor in monitors:
62 print(f"- {monitor['url']}:", uptime_robot.format_status(monitor["status"]))
65@task()
66def down(_: Context, strict: bool = False) -> None:
67 """
68 List monitors that are down (probably).
70 :param strict: If strict is True, 'seems down' is ignored
71 """
72 min_status = 9 if strict else 8
74 monitors = uptime_robot.get_monitors()
75 monitors = [_ for _ in monitors if _["status"] >= min_status]
77 for monitor in monitors:
78 print(f"- {monitor['url']}:", uptime_robot.format_status(monitor["status"]))
81def extract_friendly_name(url: str) -> str:
82 name = url.split("/")[2]
84 return name.removesuffix(".edwh.nl").removesuffix(".meteddie.nl").removeprefix("www.")
87def normalize_url(url: str) -> tuple[str, str]:
88 if not url.startswith(("https://", "http://")):
89 if "://" in url:
90 protocol = url.split("://")[0]
91 raise ValueError(f"protocol {protocol} not supported, please use http(s)://")
92 url = f"https://{url}"
94 # search for existing and confirm:
95 domain = url.split("/")[2]
97 return url, domain
100@task(aliases=("create",))
101def add(_: Context, url: str, friendly_name: str = "") -> None:
102 """
103 Create a new monitor.
104 Requires a positional argument 'url' and an optional --friendly-name label
106 :param url: Which domain name to add
107 :param friendly_name: Human-readable label (defaults to part of URL)
108 """
109 url, domain = normalize_url(url)
111 if existing := uptime_robot.get_monitors(domain):
112 print("A similar domain was already added:")
113 for monitor in existing:
114 print(monitor["friendly_name"], monitor["url"])
115 if not edwh.confirm("Are you sure you want to continue? [yN]", default=False):
116 return
118 friendly_name = friendly_name or extract_friendly_name(url)
120 monitor_id = uptime_robot.new_monitor(
121 friendly_name,
122 url,
123 )
125 if not monitor_id:
126 print("No monitor was added")
127 else:
128 print(f"Monitor '{friendly_name}' was added: {monitor_id}")
131def select_monitor(url: str) -> UptimeRobotMonitor | None:
132 """
133 Interactively select a monitor by url.
135 :param url: Which domain name to select
136 :return: Selected monitor
137 """
138 monitors = uptime_robot.get_monitors(url)
139 if not monitors:
140 print(f"No such monitor could be found {url}")
141 return None
142 if len(monitors) > 1:
143 print(f"Ambiguous url {url} could mean:")
144 for idx, monitor in enumerate(monitors):
145 print(idx + 1, monitor["friendly_name"], monitor["url"])
147 print("0", "Exit")
149 _which_one = input("Which monitor would you like to select? ")
150 if not _which_one.isdigit():
151 print(f"Invalid number {_which_one}!")
152 return None
154 which_one = int(_which_one)
155 if which_one > len(monitors):
156 print(f"Invalid selection {which_one}!")
157 return None
159 elif which_one == 0:
160 return None
161 else:
162 # zero-index:
163 which_one -= 1
165 else:
166 which_one = 0
168 return monitors[which_one]
171@task(aliases=("delete",))
172def remove(_: Context, url: str) -> None:
173 """
174 Remove a specific monitor by url.
176 :param url: Which domain name to remove
177 """
178 if not (monitor := select_monitor(url)):
179 return
181 monitor_id = monitor["id"]
183 if uptime_robot.delete_monitor(monitor_id):
184 print(f"Monitor {monitor['friendly_name']} removed!")
185 else:
186 print(f"Monitor {monitor['friendly_name']} could not be deleted.")
189@task(aliases=("update",))
190def edit(_: Context, url: str, friendly_name: Optional[str] = None) -> None:
191 """
192 Edit a specific monitor by url.
194 :param url: Which domain name to edit
195 :param friendly_name: new human-readable label
196 """
197 monitor = select_monitor(url)
198 if monitor is None:
199 return
201 monitor_id = monitor["id"]
203 url, _domain = normalize_url(url)
205 # Here you can define the new data for the monitor
206 new_data = {
207 "url": url,
208 "friendly_name": friendly_name or monitor.get("friendly_name", ""),
209 "monitor_type": monitor.get("type", MonitorType.HTTP), # todo: support more?
210 # ...
211 }
213 if uptime_robot.edit_monitor(monitor_id, new_data):
214 print(f"Monitor {monitor['friendly_name']} updated!")
215 else:
216 print(f"Monitor {monitor['friendly_name']} could not be updated.")
219@task()
220def reset(_: Context, url: str) -> None:
221 """
222 Reset a specific monitor by url.
224 :param url: Which domain name to reset
225 """
226 if not (monitor := select_monitor(url)):
227 return
229 monitor_id = monitor["id"]
231 if uptime_robot.reset_monitor(monitor_id):
232 print(f"Monitor {monitor['friendly_name']} reset!")
233 else:
234 print(f"Monitor {monitor['friendly_name']} could not be reset.")
237@task()
238def account(_: Context) -> None:
239 """
240 Show information about the acccount related to the current API key.
241 """
243 print(json.dumps(uptime_robot.get_account_details(), indent=2))