Coverage for flogin/flow/api.py: 49%
59 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-03 22:51 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-03 22:51 +0000
1from __future__ import annotations
3from typing import TYPE_CHECKING, Any, ParamSpec
5from .fuzzy_search import FuzzySearchResult
6from .plugin_metadata import PluginMetadata
8ATS = ParamSpec("ATS")
10if TYPE_CHECKING:
11 from ..jsonrpc import ExecuteResponse, JsonRPCClient, Result
13__all__ = ("FlowLauncherAPI",)
16class FlowLauncherAPI:
17 r"""This class is a wrapper around Flow's API to make it easy to make requests and receive results.
19 .. NOTE::
20 Do not initialize this class yourself, instead use :class:`~flogin.plugin.Plugin`'s :attr:`~flogin.plugin.Plugin.api` attribute to get an instance.
21 """
23 def __init__(self, jsonrpc: JsonRPCClient) -> None:
24 self.jsonrpc = jsonrpc
26 async def __call__(self, method: str, *args: Any, **kwargs: Any) -> ExecuteResponse:
27 from ..jsonrpc import ExecuteResponse
29 await getattr(self, method)(*args, **kwargs)
30 return ExecuteResponse()
32 async def fuzzy_search(
33 self, text: str, text_to_compare_it_to: str
34 ) -> FuzzySearchResult:
35 r"""|coro|
37 Asks flow how similiar two strings are.
39 Parameters
40 --------
41 text: :class:`str`
42 The text
43 text_to_compare_it_to: :class:`str`
44 The text you want to compare the other text to
46 Raises
47 -------
48 :class:`~flogin.jsonrpc.errors.JsonRPCException`
49 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
51 Returns
52 --------
53 :class:`~flogin.flow.fuzzy_search.FuzzySearchResult`
54 """
56 res = await self.jsonrpc.request("FuzzySearch", [text, text_to_compare_it_to])
58 return FuzzySearchResult(res["result"])
60 async def change_query(self, new_query: str, requery: bool = False) -> None:
61 r"""|coro|
63 Change the query in flow launcher's menu.
65 Parameters
66 --------
67 new_query: :class:`str`
68 The new query to change it to
69 requery: :class:`bool`
70 Whether or not to re-send a query request in the event that the `new_query` is the same as the current query
72 Raises
73 -------
74 :class:`~flogin.jsonrpc.errors.JsonRPCException`
75 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
77 Returns
78 --------
79 None
80 """
82 await self.jsonrpc.request("ChangeQuery", [new_query, requery])
84 async def show_error_message(self, title: str, text: str) -> None:
85 r"""|coro|
87 Triggers an error message in the form of a windows notification
89 Parameters
90 --------
91 title: :class:`str`
92 The title of the notification
93 text: :class:`str`
94 The content of the notification
96 Raises
97 -------
98 :class:`~flogin.jsonrpc.errors.JsonRPCException`
99 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
101 Returns
102 --------
103 None
104 """
106 await self.jsonrpc.request("ShowMsgError", [title, text])
108 async def show_notification(
109 self,
110 title: str,
111 content: str,
112 icon: str = "",
113 use_main_window_as_owner: bool = True,
114 ) -> None:
115 r"""|coro|
117 Creates a notification window in the bottom right hand of the user's screen
119 Parameters
120 --------
121 title: :class:`str`
122 The notification's title
123 content: :class:`str`
124 The notification's content
125 icon: :class:`str`
126 The icon to be shown with the notification, defaults to `""`
127 use_main_window_as_owner: :class:`bool`
128 Whether or not to use the main flow window as the notification's owner. Defaults to `True`
130 Raises
131 -------
132 :class:`~flogin.jsonrpc.errors.JsonRPCException`
133 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
135 Returns
136 --------
137 None
138 """
140 await self.jsonrpc.request(
141 "ShowMsg", [title, content, icon, use_main_window_as_owner]
142 )
144 async def open_settings_menu(self) -> None:
145 r"""|coro|
147 This method tells flow to open up the settings menu.
149 Raises
150 -------
151 :class:`~flogin.jsonrpc.errors.JsonRPCException`
152 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
154 Returns
155 --------
156 None
157 """
159 await self.jsonrpc.request("OpenSettingDialog")
161 async def open_url(self, url: str, in_private: bool = False) -> None:
162 r"""|coro|
164 Open up a url in the user's preferred browser, which was set in their Flow Launcher settings.
166 Parameters
167 --------
168 url: :class:`str`
169 The url to be opened in the webbrowser
170 in_private: :class:`bool`
171 Whether or not to open up the url in a private window
173 Raises
174 -------
175 :class:`~flogin.jsonrpc.errors.JsonRPCException`
176 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
178 Returns
179 --------
180 None
181 """
183 await self.jsonrpc.request("OpenUrl", [url, in_private])
185 async def run_shell_cmd(self, cmd: str, filename: str = "cmd.exe") -> None:
186 r"""|coro|
188 Tell flow to run a shell command
190 Parameters
191 --------
192 cmd: :class:`str`
193 The command to be run
194 filename: :class:`str`
195 The name of the command prompt instance, defaults to `cmd.exe`
197 Raises
198 -------
199 :class:`~flogin.jsonrpc.errors.JsonRPCException`
200 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
202 Returns
203 --------
204 None
205 """
207 await self.jsonrpc.request("ShellRun", [cmd, filename])
209 async def restart_flow_launcher(self) -> None:
210 r"""|coro|
212 This method tells flow launcher to initiate a restart of flow launcher.
214 .. WARNING::
215 Expect this method to never finish, so clean up and prepare for the plugin to be shut down before calling this.
217 Raises
218 -------
219 :class:`~flogin.jsonrpc.errors.JsonRPCException`
220 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
221 """
223 await self.jsonrpc.request("RestartApp")
225 async def save_all_app_settings(self) -> None:
226 r"""|coro|
228 This method tells flow to save all app settings.
230 Raises
231 -------
232 :class:`~flogin.jsonrpc.errors.JsonRPCException`
233 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
235 Returns
236 --------
237 None
238 """
240 await self.jsonrpc.request("SaveAppAllSettings")
242 async def save_plugin_settings(self) -> Any:
243 r"""|coro|
245 This method tells flow to save plugin settings
247 Raises
248 -------
249 :class:`~flogin.jsonrpc.errors.JsonRPCException`
250 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
252 Returns
253 --------
254 None
255 """
257 res = await self.jsonrpc.request("SavePluginSettings")
259 return res["result"]
261 async def reload_all_plugin_data(self) -> None:
262 r"""|coro|
264 This method tells flow to trigger a reload of all plugins.
266 Raises
267 -------
268 :class:`~flogin.jsonrpc.errors.JsonRPCException`
269 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
271 Returns
272 --------
273 None
274 """
276 await self.jsonrpc.request("ReloadAllPluginDataAsync")
278 async def show_main_window(self) -> None:
279 """|coro|
281 This method tells flow to show the main window
283 Raises
284 -------
285 :class:`~flogin.jsonrpc.errors.JsonRPCException`
286 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
288 Returns
289 --------
290 None
291 """
293 await self.jsonrpc.request("ShowMainWindow")
295 async def hide_main_window(self) -> None:
296 r"""|coro|
298 This method tells flow to hide the main window
300 Raises
301 -------
302 :class:`~flogin.jsonrpc.errors.JsonRPCException`
303 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
305 Returns
306 --------
307 None
308 """
310 await self.jsonrpc.request("HideMainWindow")
312 async def is_main_window_visible(self) -> bool:
313 r"""|coro|
315 This method asks flow if the main window is visible or not
317 Raises
318 -------
319 :class:`~flogin.jsonrpc.errors.JsonRPCException`
320 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
322 Returns
323 --------
324 :class:`bool`
325 """
327 res = await self.jsonrpc.request("IsMainWindowVisible")
329 return res["result"]
331 async def check_for_updates(self) -> None:
332 r"""|coro|
334 This tells flow launcher to check for updates to flow launcher
336 .. NOTE::
337 This tells flow launcher to check for updates to flow launcher, not your plugin
339 Raises
340 -------
341 :class:`~flogin.jsonrpc.errors.JsonRPCException`
342 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
344 Returns
345 --------
346 None
347 """
349 await self.jsonrpc.request("CheckForNewUpdate")
351 async def get_all_plugins(self) -> list[PluginMetadata]:
352 r"""|coro|
354 Get the metadata of all plugins that the user has installed
356 Raises
357 -------
358 :class:`~flogin.jsonrpc.errors.JsonRPCException`
359 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
361 Returns
362 --------
363 list[:class:`~flogin.flow.plugin_metadata.PluginMetadata`]
364 """
366 res = await self.jsonrpc.request("GetAllPlugins")
368 return [PluginMetadata(plugin["metadata"], self) for plugin in res["result"]]
370 async def add_keyword(self, plugin_id: str, keyword: str) -> None:
371 r"""|coro|
373 Registers a new keyword for a plugin with flow launcher.
375 Parameters
376 --------
377 plugin_id: :class:`str`
378 The id of the plugin that you want the keyword added to
379 keyword: :class:`str`
380 The keyword to add
382 Raises
383 -------
384 :class:`~flogin.jsonrpc.errors.JsonRPCException`
385 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
387 Returns
388 --------
389 None
390 """
392 await self.jsonrpc.request("AddActionKeyword", [plugin_id, keyword])
394 async def remove_keyword(self, plugin_id: str, keyword: str) -> None:
395 r"""|coro|
397 Unregisters a keyword for a plugin with flow launcher.
399 Parameters
400 --------
401 plugin_id: :class:`str`
402 The ID of the plugin that you want to remove the keyword from
403 keyword: :class:`str`
404 The keyword that you want to remove
406 Raises
407 -------
408 :class:`~flogin.jsonrpc.errors.JsonRPCException`
409 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
411 Returns
412 --------
413 None
414 """
416 await self.jsonrpc.request("RemoveActionKeyword", [plugin_id, keyword])
418 async def open_directory(self, directory: str, file: str | None = None) -> None:
419 r"""|coro|
421 Opens up a folder in file explorer. If a file is provided, the file will be pre-selected.
423 Parameters
424 --------
425 directory: :class:`str`
426 The directory you want to open
427 file: Optional[:class:`str`]
428 The file in the directory that you want to highlight, defaults to `None`
430 Raises
431 -------
432 :class:`~flogin.jsonrpc.errors.JsonRPCException`
433 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
435 Returns
436 --------
437 None
438 """
440 await self.jsonrpc.request("OpenDirectory", [directory, file])
442 async def update_results(self, raw_query: str, results: list[Result[Any]]) -> None:
443 r"""|coro|
445 Tells flow to change the results shown to the user
447 .. NOTE::
448 The ``raw_query`` parameter is required by flow launcher, and must be the same as the current raw query in flow launcher for the results to successfully update.
450 Parameters
451 ----------
452 raw_query: :class:`str`
453 Only change the results if the current raw query is the same as this
454 results: list[:class:`~flogin.jsonrpc.results.Result`]
455 The new results
457 Raises
458 -------
459 :class:`~flogin.jsonrpc.errors.JsonRPCException`
460 This is raised when an error happens with the JsonRPC pipe while attempting to call this API method.
462 Returns
463 -------
464 None
465 """
467 from ..jsonrpc import QueryResponse # circular import
469 self.jsonrpc.plugin._results.update({res.slug: res for res in results})
471 await self.jsonrpc.request(
472 "UpdateResults", [raw_query, QueryResponse(results).to_dict()["result"]]
473 )