diff --git a/docs/server-api-v1/scripts.md b/docs/server-api-v1/scripts.md index 338cc00..1a32d3a 100644 --- a/docs/server-api-v1/scripts.md +++ b/docs/server-api-v1/scripts.md @@ -5,12 +5,10 @@ ### SCRIPT_STRUCT ```json { - "id": 11, "alias": "bad_weather_light", "filename": "bad_weather_light.php", "path": "/home/smartserver/scripts", "state": "enabled", // | disabled - "added_by": 12,// user_id "created_by": "Eugene Sukhodolskiy", // Автор скрипта, брать будет из самого скрипта "create_at": "2025-06-02 23:35:11" } @@ -18,13 +16,13 @@ --- -### GET `/api/v1/scripts/list` +### GET `/api/v1/scripts/actions/list` Получить список скриптов #### Пример ответа ```json { - "status": "ok", + "status": true, "scripts": [ "SCRIPT_STRUCT" // ... @@ -35,20 +33,17 @@ --- -### GET `/api/v1/scripts/id/{{id}}` OR GET `/api/v1/scripts/alias/{{alias}}` +### GET `/api/v1/scripts/scope/filename/{{filename}}` Получить выбраный скрипт #### Пример ответа -```json - { - "status": "ok", - "scripts": "SCRIPT_STRUCT" - } +```php + ``` --- -### POST `/api/v1/scripts/new` +### POST `/api/v1/actions/scripts/new` Зарегистрировать в системе новый скрипт - По умолчанию, новый добавленый скрипт - не активен, имеет `state=disabled` @@ -72,7 +67,7 @@ --- -### POST `/api/v1/scripts/id/{{id}}/update` +### POST `/api/v1/scripts/actions/alias/{{alias}}/update` Редактировать скрипт #### Пример запроса @@ -81,14 +76,13 @@ "alias": "bad_weather_light", "filename": "bad_weather_light.php", "path": "/home/smartserver/scripts", - "id": 11 // id существующего скрипта } ``` #### Пример НЕ успешного ответа. Невалидные поля ```json { - "status": "error", + "status": false, "field": "alias", "message": "Alias already exists" // | "File not exists" | "Script by id not found" } @@ -96,46 +90,46 @@ --- -### GET `/api/v1/scripts/id/{{id}}/enable` +### GET `/api/v1/scripts/actions/alias/{{alias}}/enable` Включить скрипт #### Пример ответа ```json { - "status": "ok", + "status": true, "scripts": "SCRIPT_STRUCT" } ``` --- -### GET `/api/v1/scripts/id/{{id}}/disable` +### GET `/api/v1/scripts/actions/alias/{{alias}}/disable` Отключить скрипт #### Пример ответа ```json { - "status": "ok", + "status": true, "scripts": "SCRIPT_STRUCT" } ``` --- -### GET `/api/v1/scripts/id/{{id}}/remove` +### GET `/api/v1/scripts/actions/alias/{{alias}}/remove` Удалить скрипт из системы. (Сам скрипт при этом вполне может оставаться в файловой системе) #### Пример ответа ```json { - "status": "ok", + "status": true, "scripts": "SCRIPT_STRUCT" } ``` --- -### POST `/api/v1/scripts/id/{{id}}/run` OR POST `/api/v1/scripts/alias/{{alias}}/run` +### POST `/api/v1/scripts/actions/run` Запустить выполнение скрипта. - При этом проверяется от имени какого пользователя был запущен скрипт. - Если прав пользователя не хватает - скрипт не запуститься. @@ -144,6 +138,7 @@ #### Пример запроса ```json { + "alias": "script_alias", "params": { // ... } @@ -153,7 +148,7 @@ #### Пример ответа ```json { - "status": "ok", + "status": true, "script": "SCRIPT_STRUCT", "result": { // ... diff --git a/server/ControlScripts/TestScriptsScope.php b/server/ControlScripts/TestScriptsScope.php index 325c646..84505fa 100644 --- a/server/ControlScripts/TestScriptsScope.php +++ b/server/ControlScripts/TestScriptsScope.php @@ -9,6 +9,17 @@ $this -> stand_btn_pressed_to_stand_relay(); } + public function register_actions_scripts(): void { + $this -> add_action_script([ + "alias" => "script_alias", + "name" => "script name", + "description" => "script description", + "author" => "Eugene Sukhodolskiy" + ], function($params) { + return ["test", $params]; + }); + } + public function register_regular_scripts(): void { $this -> add_regular_script("testing1", function() { $button = $this -> devices() -> by_alias("test_device_btn"); diff --git a/server/SHServ/Controllers/CronController.php b/server/SHServ/Controllers/CronController.php index 845879f..8c15b92 100644 --- a/server/SHServ/Controllers/CronController.php +++ b/server/SHServ/Controllers/CronController.php @@ -4,18 +4,16 @@ use \SHServ\Models\Devices; use \SHServ\Tools\DeviceScanner; +use \SHServ\Middleware\ControlScripts; class CronController extends \SHServ\Middleware\Controller { public function run_regular_cron_scripts() { // В будущем: фильтруем список, отсеивая те скрипты, что выключены - $scopes = app() -> control_scripts_instances; - foreach($scopes as $scope_name => $scope) { - $scripts = $scope -> get_regular_scripts(); + $regular_scripts = ControlScripts::get_regular_scripts(); - foreach($scripts as $script_alias => $script) { - $script(); - } + foreach($regular_scripts as $alias => $script) { + $script(); } } diff --git a/server/SHServ/Controllers/ScriptsRESTAPIController.php b/server/SHServ/Controllers/ScriptsRESTAPIController.php new file mode 100644 index 0000000..56fa5a7 --- /dev/null +++ b/server/SHServ/Controllers/ScriptsRESTAPIController.php @@ -0,0 +1,41 @@ + utils() -> response_error("action_script_not_found"); + } + + return $this -> utils() -> response_success([ + "return" => $result + ]); + } + + public function actions_scripts_list() { + $scripts = ControlScripts::get_actions_scripts(); + + $data = []; + + foreach($scripts as $alias => $script_data) { + $data[] = [ + "alias" => $alias, + "name" => $script_data["attributes"]["name"], + "description" => $script_data["attributes"]["description"], + "filename" => $script_data["attributes"]["filename"], + "path" => $script_data["attributes"]["path"], + "created_by" => $script_data["attributes"]["author"], + ]; + } + + return $this -> utils() -> response_success([ + "scripts" => $data, + "total" => count($data) + ]); + } +} \ No newline at end of file diff --git a/server/SHServ/Implements/ControlScriptsInterface.php b/server/SHServ/Implements/ControlScriptsInterface.php index 0740ff3..7b656bb 100644 --- a/server/SHServ/Implements/ControlScriptsInterface.php +++ b/server/SHServ/Implements/ControlScriptsInterface.php @@ -18,4 +18,10 @@ * @return void */ public function register_regular_scripts(); + + /** + * Этот метод существует для того, чтоб в нём регистрировали необходимые скрипты, что будут вызываться из вне вручную, или из другого скрипта + * @return void + */ + public function register_actions_scripts(); } \ No newline at end of file diff --git a/server/SHServ/Middleware/ControlScripts.php b/server/SHServ/Middleware/ControlScripts.php index deac544..0a702f7 100644 --- a/server/SHServ/Middleware/ControlScripts.php +++ b/server/SHServ/Middleware/ControlScripts.php @@ -6,14 +6,17 @@ abstract class ControlScripts { protected $devices_model; - protected $regular_scripts; + protected static $regular_scripts = []; + protected static $actions_scripts = []; abstract protected function register_events_handlers(): void; abstract protected function register_regular_scripts(): void; + abstract protected function register_actions_scripts(): void; public function __construct() { $this -> register_events_handlers(); $this -> register_regular_scripts(); + $this -> register_actions_scripts(); } protected function add_event_handler(String $event_name, callable $handler): void { @@ -31,10 +34,59 @@ } protected function add_regular_script(String $alias, callable $script): void { - $this -> regular_scripts[$alias] = $script; + self::$regular_scripts[$alias] = $script; } - public function get_regular_scripts(): Array { - return $this -> regular_scripts; + public static function get_regular_scripts(): Array { + return self::$regular_scripts; + } + + public static function get_actions_scripts(): Array { + return self::$actions_scripts; + } + + public function add_action_script(Array $attributes, callable $script): bool { + if(!isset($attributes["alias"])) { + return false; + } + + if(isset(self::$actions_scripts[$attributes["alias"]])) { + return false; + } + + $ref = new \ReflectionClass(static::class); + $path_info = pathinfo($ref -> getFileName()); + + $attributes["name"] = $attributes["name"] ?? "unknown"; + $attributes["description"] = $attributes["description"] ?? ""; + $attributes["classname"] = static::class; + $attributes["path"] = $path_info["dirname"]; + $attributes["filename"] = $path_info["basename"]; + $attributes["author"] = $attributes["author"] ?? "Unknown author"; + + self::$actions_scripts[$attributes["alias"]] = [ + "attributes" => $attributes, + "script" => $script + ]; + + return true; + } + + public static function run_action_script(String $alias, Array $params): Array | null { + if(!isset(self::$actions_scripts[$alias])) { + return null; + } + + $start_time = microtime(true); + + $result = self::$actions_scripts[$alias]["script"]($params); + + $exec_time = microtime(true) - $start_time; + $exec_time = round($exec_time, 3); + + return [ + "result" => $result, + "exec_time" => "{$exec_time} seconds" + ]; } } \ No newline at end of file diff --git a/server/SHServ/Routes.php b/server/SHServ/Routes.php index 067cd77..c91c991 100644 --- a/server/SHServ/Routes.php +++ b/server/SHServ/Routes.php @@ -5,7 +5,8 @@ class Routes { use \SHServ\Routes\DevMode; - use \SHServ\Routes\RESTAPI_v1; + use \SHServ\Routes\DevicesRESTAPI_v1; + use \SHServ\Routes\ScriptsRESTAPI_v1; /** * Instance of Router module @@ -33,9 +34,13 @@ $this -> get_routes(); $this -> post_routes(); - $this -> restapi_uri_routes(); - $this -> restapi_get_routes(); - $this -> restapi_post_routes(); + $this -> devices_restapi_uri_routes(); + $this -> devices_restapi_get_routes(); + $this -> devices_restapi_post_routes(); + + $this -> scripts_restapi_uri_routes(); + $this -> scripts_restapi_get_routes(); + $this -> scripts_restapi_post_routes(); // DEV MODE if(FCONF["devmode"]) { diff --git a/server/SHServ/Routes/DevicesRESTAPI_v1.php b/server/SHServ/Routes/DevicesRESTAPI_v1.php new file mode 100644 index 0000000..e5f370a --- /dev/null +++ b/server/SHServ/Routes/DevicesRESTAPI_v1.php @@ -0,0 +1,34 @@ + router -> uri("/api/v1/devices/scanning/setup", "{$this -> cn}\\DevicesRESTAPIController@scanning__ready_to_setup"); + $this -> router -> uri("/api/v1/devices/scanning/all", "{$this -> cn}\\DevicesRESTAPIController@scanning__all"); + + $this -> router -> uri('/api/v1/devices/id/$device_id/reboot', "{$this -> cn}\\DevicesRESTAPIController@reboot_device"); + $this -> router -> uri('/api/v1/devices/id/$device_id/remove', "{$this -> cn}\\DevicesRESTAPIController@remove_device"); + $this -> router -> uri('/api/v1/devices/id/$device_id/info', "{$this -> cn}\\DevicesRESTAPIController@device_info"); + $this -> router -> uri('/api/v1/devices/id/$device_id', "{$this -> cn}\\DevicesRESTAPIController@device"); + $this -> router -> uri('/api/v1/devices/id/$device_id/status', "{$this -> cn}\\DevicesRESTAPIController@device_status"); + } + + protected function devices_restapi_post_routes() { + $this -> router -> post( + [ "device_ip", "alias", "name", "description" ], + "{$this -> cn}\\DevicesRESTAPIController@setup_new_device", + "/api/v1/devices/setup/new-device" + ); + + $this -> router -> post( + [ "device_id", "action", "params" ], + "{$this -> cn}\\DevicesRESTAPIController@do_device_action", + "/api/v1/devices/action" + ); + } + + protected function devices_restapi_get_routes() { + + } +} \ No newline at end of file diff --git a/server/SHServ/Routes/RESTAPI_v1.php b/server/SHServ/Routes/RESTAPI_v1.php deleted file mode 100644 index 8dafade..0000000 --- a/server/SHServ/Routes/RESTAPI_v1.php +++ /dev/null @@ -1,34 +0,0 @@ - router -> uri("/api/v1/devices/scanning/setup", "{$this -> cn}\\DevicesRESTAPIController@scanning__ready_to_setup"); - $this -> router -> uri("/api/v1/devices/scanning/all", "{$this -> cn}\\DevicesRESTAPIController@scanning__all"); - - $this -> router -> uri('/api/v1/devices/id/$device_id/reboot', "{$this -> cn}\\DevicesRESTAPIController@reboot_device"); - $this -> router -> uri('/api/v1/devices/id/$device_id/remove', "{$this -> cn}\\DevicesRESTAPIController@remove_device"); - $this -> router -> uri('/api/v1/devices/id/$device_id/info', "{$this -> cn}\\DevicesRESTAPIController@device_info"); - $this -> router -> uri('/api/v1/devices/id/$device_id', "{$this -> cn}\\DevicesRESTAPIController@device"); - $this -> router -> uri('/api/v1/devices/id/$device_id/status', "{$this -> cn}\\DevicesRESTAPIController@device_status"); - } - - protected function restapi_post_routes() { - $this -> router -> post( - [ "device_ip", "alias", "name", "description" ], - "{$this -> cn}\\DevicesRESTAPIController@setup_new_device", - "/api/v1/devices/setup/new-device" - ); - - $this -> router -> post( - [ "device_id", "action", "params" ], - "{$this -> cn}\\DevicesRESTAPIController@do_device_action", - "/api/v1/devices/action" - ); - } - - protected function restapi_get_routes() { - - } -} \ No newline at end of file diff --git a/server/SHServ/Routes/ScriptsRESTAPI_v1.php b/server/SHServ/Routes/ScriptsRESTAPI_v1.php new file mode 100644 index 0000000..b65076d --- /dev/null +++ b/server/SHServ/Routes/ScriptsRESTAPI_v1.php @@ -0,0 +1,22 @@ + router -> uri("/api/v1/scripts/actions/list", "{$this -> cn}\\ScriptsRESTAPIController@actions_scripts_list"); + } + + protected function scripts_restapi_post_routes() { + $this -> router -> post( + [ "alias", "params" ], + "{$this -> cn}\\ScriptsRESTAPIController@run_action_script", + '/api/v1/scripts/actions/run' + ); + + } + + protected function scripts_restapi_get_routes() { + + } +} \ No newline at end of file diff --git a/server/SHServ/text-msgs.php b/server/SHServ/text-msgs.php index 5f527e9..02c4e84 100644 --- a/server/SHServ/text-msgs.php +++ b/server/SHServ/text-msgs.php @@ -34,6 +34,7 @@ "device_mode_error" => "", "db_error" => "", "device_error_of_auth" => "", + "action_script_not_found" => "", // Other "accept_removing" => "Подтвердите удаление",