├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── alisa ├── blocks ├── actions.json └── payload.json ├── composer.json ├── composer.lock ├── index.php ├── settings.yml ├── src ├── Alisa.php ├── database │ ├── images.config.json │ └── images.data.json ├── handler.php └── traits │ └── SBlock.php └── test.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | alisa_log.txt 4 | README.md 5 | images/1.jpg 6 | images/2.jpg -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 7.2 4 | - 7.1 5 | - 7.0 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Danil005 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # PHP-YANDEX-ALISA 4 | 5 | Библиотека для работы с Алисой. 6 | Пример блоковой системы находиться в папке blocks. 7 | ___ 8 | 9 | ## Содержание 10 | 11 | 1. [TODO](#todo) 12 | 2. [Установка](#%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0) 13 | 3. [Описание констант](#%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BA%D0%BE%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82) 14 | 4. [Описание переменных](#%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%BD%D1%8B%D1%85) 15 | 5. [Описание методов](#%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5-%D0%BC%D0%B5%D1%82%D0%BE%D0%B4%D0%BE%D0%B2) 16 | 6. [Система JSON-блоков](#Система-json-блоков) 17 | + [Что это такое?](#Что-это-такое) 18 | + [Файлы обработки](#Файлы-обработки) 19 | + [Описание Action](#Описание-action) 20 | + [Простой пример](#Простой-пример) 21 | + [Пример с вариацией сообщений](#Пример-с-вариацией-сообщений) 22 | + [Пример с добавлением кнопки](#Пример-с-добавлением-кнопки) 23 | + [Пример с подготовленные запросы](#Пример-с-подготовленные-запросы) 24 | + [Группировка prepare и question](#Группировка-prepare-и-question) 25 | + [Пример кода с кнопками и payload](#Пример-кода-с-кнопками-и-payload) 26 | + [Пример сложного JSON-блока](#Пример-сложного-json-блока) 27 | + [Описание Payload](#Описание-payload) 28 | + [Пример запроса](#Пример-запроса) 29 | + [Форматирование текста](#Форматирование-текста) 30 | 7. [Консоль Алиса](#Консоль-Алиса) 31 | + [Получить загруженные файлы](#php-alisa-uploadget) 32 | + [Загрузить с сервера](#php-alisa-uploadfile-file_name) 33 | + [Загрузить с сайта](#php-alisa-uploadurl-url) 34 | 9. [index.php](#indexphp) 35 | 10. [setting.yml](#settingyml) 36 | 11. [Локальный Webhook.](#%D0%9B%D0%BE%D0%BA%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9-webhook) 37 | 38 | ___ 39 | ## TODO 40 | |Дата|Описание релиза |Состояние 41 | |:--:|--|--| 42 | | 5.08.2018 |Теперь можно делать вариации вопросов и ответов. |**done** 43 | | 5.08.2018 |Выполнять payload-функции (callback). |**done** 44 | | 5.08.2018 |Проверка на орфографию. |**done** 45 | | 6.08.2018 |Поддержка подготовленных запросов. |**done** 46 | | 8.08.2018 |Реализация созданий навыков при помощи JSON-блоков. |**done** 47 | | 11.08.2018 |Отправка сообщений с фотографиями. |**done 80%** 48 | |---|Оплата при помощи компании Unitpay. |**in plan** 49 | 50 | ## Установка 51 | ``` 52 | composer require danil005/php-yandex-alisa:dev-master 53 | ``` 54 | ## Описание констант 55 | ### SKILL_NAME 56 | Название навыка. 57 | ___ 58 | ### VERSION 59 | Версия Алиса API. По умолчанию: 1.0 60 | ## Описание переменных 61 | ### private $startMessage = "" 62 | Сообщение, которое будет отображаться при старте навыка. 63 | ___ 64 | ### private $startMessageTTS = "" 65 | Сообщение, которое будет озвучено синтезом речи Yandex. 66 | ___ 67 | ### private $startButton = [] 68 | Кнопки, которые будут отображены при запуске навыка 69 | ___ 70 | ### private $version = self::VERSION 71 | Наследует константу VERSION. 72 | ___ 73 | ### private $anyMessage = "Простите, я вас не понимаю." 74 | Сообщение, которое будет отправлено пользователю в случае, если команда не будет найдена. 75 | ___ 76 | ### private $caseSensitive = true 77 | Чувствительность к регистру сообщений. 78 | ___ 79 | ### private $speller = false 80 | Проверка на орфографию. 81 | ___ 82 | ### public $vars = [] 83 | Переменная для обработки [Prepare-функции](#public-preparestring-getmessage-string-command-bool). 84 | ___ 85 | ### private $request = [] 86 | Переменная, которая получает ответ от Алисы. 87 | ___ 88 | ### public $imagesDir = "images" 89 | Директория с изображениями. 90 | ___ 91 | ### public $response = stdObject 92 | Переменная для формирования ответа на полученный запрос от Алисы. 93 | ## Описание методов 94 | ### public setCaseSensitive(bool $sensitive = true): $this 95 | Метод, который меняет чувствительность к регистру. 96 | `TRUE` - включить чувствительность. 97 | `FALSE` - выключить чувствительность. 98 | 99 | |Аргумент|Тип| Описание |По умолчанию 100 | |:--:|--|--|-- 101 | |sensitive|bool|Чувствительно к регистру. |true 102 | ___ 103 | ### public setImagesDir(String $path): $this 104 | Устанавливает директорию с изображениями. 105 | |Аргумент|Тип| Описание |По умолчанию 106 | |:--:|--|--|-- 107 | |path|String|Директория с изображениями. |Обязательно 108 | ___ 109 | ### public setAny(String $message): $this 110 | Метод, который устанавливает сообщение по умолчанию, если чат-бот не смог понять, что от него хотят. 111 | 112 | |Аргумент|Тип| Описание |По умолчанию 113 | |:--:|--|--|-- 114 | |message|String|Текст сообщения. |Обязательно 115 | ___ 116 | ### public setVersion(String $version = self::VERSION): $this 117 | Метод, который устанавливает версию Алиса API. 118 | 119 | |Аргумент|Тип| Описание |По умолчанию 120 | |:--:|--|--|-- 121 | |version|String|Версия Алиса API. |Данные с константы VERSION 122 | ___ 123 | ### public setSpellerCorrect(bool $speller = false): $this 124 | Исправление ошибок в тексте. 125 | 126 | |Аргумент|Тип| Описание |По умолчанию 127 | |:--:|--|--|-- 128 | |speller|bool|Установить проверку на орфографию и ее исправления в случае нахождении ошибки. |false 129 | ___ 130 | ### public setEndMessage(): $this 131 | Метод, который завершает сессию и закрывает навык. 132 | ___ 133 | 134 | ### public addStartMessage(String $message): $this 135 | Метод, который устанавливает сообщение при старте навыка. 136 | 137 | |Аргумент|Тип| Описание |По умолчанию 138 | |:--:|--|--|-- 139 | |message|String|Текст сообщения. |Обязательно 140 | ___ 141 | ### public addStartTTS(String $message): $this 142 | Метод, который устанавливает сообщение при старте навыка для синтеза речи. 143 | 144 | |Аргумент|Тип| Описание |По умолчанию 145 | |:--:|--|--|-- 146 | |message|String|Текст сообщения. |Обязательно 147 | ___ 148 | ### public addStartButton(String $title, bool $hide = false, Array $payload = [], String $url = null): $this 149 | Метод, который устанавливает кнопки при старте навыка. 150 | 151 | |Аргумент|Тип| Описание |По умолчанию 152 | |:--:|--|--|-- 153 | |title |String|Название кнопки. |Обязательно 154 | |hide|bool|Спрятать кнопки после нажатия.|false 155 | |payload|Array|Отправить дополнительные данные для обработки.|[] 156 | |url|String|URL-ссылка|null 157 | ___ 158 | ### public addButton(String $title, bool $hide = false, Array $payload = [], String $url = null): $this 159 | Метод, который устанавливает кнопки. 160 | 161 | 162 | **ВНИМАНИЕ!** 163 | **Обязательно перед этим методом использовать sendMessage();** 164 | 165 | |Аргумент|Тип| Описание |По умолчанию 166 | |:--:|--|--|-- 167 | |title |String|Название кнопки. |Обязательно 168 | |hide|bool|Спрятать кнопки после нажатия.|false 169 | |payload|Array|Отправить дополнительные данные для обработки.|[] 170 | |url|String|URL-ссылка|null 171 | ___ 172 | ### public sendMessage(String $message, String $tts = "", bool $speller = false ): $this 173 | Отправить сообщение пользователю. 174 | Использовать speller в этом методе не так важно, ведь вы сами можете вводить корректный текст, однако если вы не уверены в написании или боитесь, что где-то сделали опечатку, то можете использовать этот аргумент и поставить его на `TRUE`. 175 | Также использование аргумента speller очень хорошо сочетается с методом [prepare](#public-preparestring-getmessage-string-command-bool). 176 | 177 | |Аргумент|Тип| Описание |По умолчанию 178 | |:--:|--|--|-- 179 | |message|String|Текст сообщения. |Обязательно 180 | |tts|String|Синтез речи, ударения, паузы.|"" 181 | |speller|bool|Проверка на орфографию и исправление, если будет найдена ошибка.|false 182 | ___ 183 | ### public sendImage(String $path, String $title = "", String $description = "", Array $options = []): $this 184 | Метод, которые отобразить изображение. Если указать его, то sendMessage вызывать нет смысла. 185 | **Внимание, чтобы отобразить изображение, вам необходимо его загрузить на сервер Yandex. Для этого создана консоль - alisa.** 186 | 187 | |Аргумент|Тип| Описание |По умолчанию 188 | |:--:|--|--|-- 189 | |path|String|Название файла. |Обязательно 190 | |title|String|Подпись под фотографией|"" 191 | |description|String|Описание под фотографией|"" 192 | |options|Array|Дополнительные настройки|[] 193 | 194 | #### Дополнительные настройки: 195 | |Аргумент|Тип| Описание 196 | |:--:|--|--|-- 197 | |url|String|Web-ссылка. 198 | |payload|Array|Payload-запрос. 199 | ___ 200 | ### public sendGallery(Array $images, String $headerText = "", String $footerText = "", Array $footerOpt = []): $this 201 | Метод, которые отобразить галерею. Если указать его, то sendMessage вызывать нет смысла. 202 | **Внимание, чтобы отобразить изображение, вам необходимо его загрузить на сервер Yandex. Для этого создана консоль - alisa.** 203 | 204 | 205 | |Аргумент|Тип| Описание |По умолчанию 206 | |:--:|--|--|-- 207 | |images|Array|Массив с изображениями. |Обязательно 208 | |headerText|String|Заголовок галереи.|"" 209 | |footerText|String|Текст под изображениями.|"" 210 | |footerOpt|Array|Дополнительные настройки|[] 211 | 212 | #### Дополнительные настройки: 213 | |Аргумент|Тип| Описание 214 | |:--:|--|--|-- 215 | |url|String|Web-ссылка. 216 | |payload|Array|Payload-запрос. 217 | |message|String|Сообщение, которое будет отправлено при нажатии на кнопку. 218 | ___ 219 | ### protected optionsQuestions(Array $list, String $command): bool 220 | Вариация реагирования на фразы для выполнения определенного дейсвтия указанного в 221 | [cmd()](#public-cmdstring-command). 222 | 223 | |Аргумент|Тип| Описание |По умолчанию 224 | |:--:|--|--|-- 225 | |list|Array|Лист ключевых слов для вызова действия. |Обязательно 226 | |command|String|Команда пришедшая от пользователя на сервер.|Обязательно 227 | ___ 228 | ### protected optionsAnswers(Array $list): mixed 229 | Отправить вариационный ответ пользователю. Например, если вы не хотите отправлять пользователю одно и тоже сообщение, то можно использовать этот метод и расширить диапазон речи. 230 | 231 | |Аргумент|Тип| Описание |По умолчанию 232 | |:--:|--|--|-- 233 | |list|array|Лист фраз, которые будет выдавать Алиса-навык. |Обязательно 234 | ___ 235 | ### protected optionsCallback(Array $list, Array $callback): $this 236 | Метод, который позволяет делать логическую операцию ИЛИ. В этом случае указывается набор 237 | фраз, которые возможны при возврате payload (Callback). В случае если это слово будет найдено, то выдает `TRUE`. Также можно отправлять несколько Payload для одного действия и тем самым через эту функцию написать их оба. 238 | 239 | |Аргумент|Тип| Описание |По умолчанию 240 | |:--:|--|--|-- 241 | |list|Array|Лист ключевых слов. |Обязательно 242 | |callback|String|Обязательная переменная, которая передается в функцию для обработки.|Обязательно 243 | ___ 244 | ### public prepare(String $getMessage, String $command): bool 245 | Метод, который позволяет делать подготовленные запросы и в последствии выводить их. Возвращает `true` или `false`, а также записывает результат функции в переменную `$this->vars`. 246 | 247 | Пример: 248 | 249 | if( $this->prepare("Купить {what} за {price}", $command) ) { 250 | $this->sendMessage("Вы уверены, что хотите купить 251 | {$this->vars['whats']} за {$this->vars['price']}₽?"); 252 | return true; 253 | } 254 | 255 | Как вы можете заметить, ключи переменной vars отображают подготовленные ключи из аргумента `String $getMessage`. 256 | 257 | |Аргумент|Тип| Описание |По умолчанию 258 | |:--:|--|--|-- 259 | |getMessage|String|Сообщение, которое должен принять навык для обработки данных. |Обязательно 260 | |command|String|Сообщение которое придет от пользователя.|Обязательно 261 | ___ 262 | ### public listen(): bool|null 263 | Начать прослушивать Webhook. 264 | **Данный метод обязательно указывать в конце цепочки.** 265 | ___ 266 | ### public cmd(String $command) 267 | Метод в котором необходимо обрабатывать все данные. 268 | **Обязательно указывать** `return true;` **после каждого условия.** 269 | 270 | if( $command == "привет" ) { 271 | $this->sendMessage("Приветик")->addButton("А что ты умеешь?"); 272 | return true; 273 | } 274 | //Или 275 | if( $this->optionsQuestions(["привет", "здравствуйте"]) ) { 276 | $this 277 | ->sendMessage($this->optionsAnswers(["Добрый день!", "Я рада вас видеть!"])) 278 | ->addButton("А что ты умеешь?"); 279 | return true; 280 | } 281 | //Или 282 | if( $this->prepare("забронируй мне {what} на {time} в {when}", $command) ) { 283 | $this->sendMessage 284 | ("Мы забронировали 285 | {$this->vars['what']} 286 | на {$this->vars['time']} 287 | в {$this->vars['when']}" 288 | ); 289 | return true; 290 | } 291 | 292 | return false; 293 | 294 | ___ 295 | ### public payload(Array $callback) 296 | Метод в котором необходимо обрабатывать все данные пришедших с payload.. 297 | **Обязательно указывать** `return true;` **после каждого условия.** 298 | 299 | if( array_key_exists('help', $callback) ) { 300 | $this->sendMessage('Много чего! А ты?'); 301 | return true; 302 | } 303 | //Или 304 | if( $this->optionsCallback(["help", "helpme"], $callback) ) { 305 | $this->sendMessage('Много чего! А ты?'); 306 | return true; 307 | } 308 | return false; 309 | ___ 310 | ## Система JSON-блоков 311 | Просто, удобно, быстро. 312 | Чтобы активировать блоковую систему, укажите в index.php (или в другом файле) метод `setBlocksActions(true)`. 313 | ___ 314 | ### Что это такое? 315 | Система JSON-блоков построена таким образом, чтобы можно было использовать SDK не трогая навыки программирования. Вам достаточно прочитать эту документацию и делать уже сейчас свои навыки. Пока эта система находиться на Alpha-стадии. 316 | ___ 317 | ### Файлы обработки 318 | Всего 2 файла обработки: 319 | 320 | |Файл|Описание|Местонахождение 321 | |:--:|--|-- 322 | |action.json|Главный файл, который берет на себя ответственность выполнять определенны действия.|\dir_project\blocks\action.json 323 | |payload.json|Файл для обработки payload запросов (callback).|\dir_project\blocks\payload. 324 | 325 | **Если у вас стоит `setCaseSensitive(false)`, то обязательно писать маленькими буквами, разрешает писать хаотично в send-теле.** 326 | ___ 327 | ### Описание Action 328 | Главный файл блоковой системы. 329 | 330 | #### Простой пример: 331 | Это маленький пример, который демонстрирует работу навыка уже с готовым json-блоком. Он ограничен действиями, однако может прост в понимании. 332 | 333 | [ 334 | { 335 | "question": "привет", 336 | "send": { 337 | "message": "Добрый день!", 338 | "tts": "Д+обрый---д+ень!" 339 | } 340 | } 341 | ] 342 | |Аргумент|Тип данных|Описание| 343 | |--|--|-- 344 | |question|String|Сообщение, которое будет писать пользователь. 345 | |send|Array|Ответить на сообщение навыку. 346 | |message|String|Сообщение, которое будет отправлено в ответ. 347 | |tts|String|Синтез речи. 348 | 349 | #### Пример с вариацией сообщений: 350 | Иногда хочется, чтобы навык реагировал на несколько фраз, а также отвечал не одним предложением, а каким-нибудь разным. 351 | 352 | [ 353 | { 354 | "question": [ 355 | "привет", "добрый день", "здравствуйте" 356 | ], 357 | "send": { 358 | "message": ["Добрый день", "С новым годом!"], 359 | "tts": ["Д+обрый---д+ень!", "С н+овым г+одом!"] 360 | } 361 | } 362 | ] 363 | |Аргумент|Тип данных|Описание| 364 | |--|--|-- 365 | |question|Array|Сообщение, которое будет писать пользователь. 366 | |send|Array|Ответить на сообщение навыку. 367 | |message|Array|Сообщение, которое будет отправлено в ответ. 368 | |tts|Array|Синтез речи. 369 | 370 | **ВНИМАНИЕ** 371 | Рекомендуем указывать вариацию ответов в одинаковом порядке с синтезом речи, дабы не было разногласия: текст - один, а слова речи -другие. 372 | 373 | #### Пример с добавлением кнопки: 374 | Кнопки необходимо добавлять внутри тела send, там и прописывать логику. 375 | 376 | ... 377 | }, 378 | "buttons": { 379 | "title": "button1", 380 | "hide": false, 381 | "payload": [], 382 | "url": null 383 | } 384 | |Аргумент|Тип данных|Описание| 385 | |--|--|-- 386 | |buttons|Array|Объявление кнопок в теле send. 387 | |title|String|Название кнопки. 388 | |hide|Bool|Спрятать кнопку после нажатия. 389 | |payload|Array|Аналог callback, отправляет данные на сервер. Дальше будет расписано, как можно будет это использовать. 390 | |url|String|Кнопка с ссылкой. 391 | 392 | 393 | Кнопок можно добавить несколько, для этого просто сделайте `buttons` как массив: 394 | 395 | 396 | ... 397 | }, 398 | "buttons": [ 399 | { 400 | "title": "button1", 401 | "hide": false, 402 | "payload": [], 403 | "url": null 404 | }, 405 | { 406 | "title": "button2", 407 | "hide": false, 408 | "payload": [], 409 | "url": null 410 | }, 411 | ... 412 | ] 413 | #### Пример с подготовленные запросы: 414 | Подготовленные запросы - это сложная конструкция позволяющая вам создавать различные запросы, например: забронируй гостиницу на пятницу 415 | в 15:40. Запрос будет выглядеть таким образом: 416 | 417 | `забронировать {what} на {when} в {time}` 418 | Такая конструкция может быть **за место question**. 419 | 420 | 421 | [ 422 | { 423 | "prepare": "купить {what}", 424 | "send": { 425 | "message": "Вы купили {what}!" 426 | "tts": "Вы куп+или {what}!" 427 | }, 428 | ... 429 | } 430 | ] 431 | |Аргумент|Тип данных|Описание| 432 | |--|--|-- 433 | |prepare|String|Подготовленный запрос. Переменная указывается в фигурных скобках. Она может быть любой, но **должна начинаться с буквы**. 434 | 435 | Переменные можно указывать в send-теле для отображения того, что написал пользователь. 436 | #### Группировка prepare и question: 437 | Вы также можете группировать вместе подготовленные запросы и обычные. Непосредственно в обоих этих методах возможно использовать вариацию. Однако блоковая система станет сложнее: 438 | 439 | [ 440 | { 441 | "question": ["купить", "приобрести"], 442 | "prepare": ["купить {what}", "приобрести {what}"], 443 | "send": { 444 | "message": "Покупаем..." , 445 | "tts": "Покупаем..." 446 | ... 447 | } 448 | ] 449 | 450 | Также можно разделить ответы и создать их опциональными: 451 | 452 | [ 453 | { 454 | "question": ["купить", "приобрести"], 455 | "prepare": ["купить {what}", "приобрести {what}"], 456 | "send": { 457 | "message": { 458 | "question": "Покупаем...", 459 | "prepare": "Покупаем {what}..." 460 | }, 461 | "tts": { 462 | "question": "Покуп+аем...", 463 | "prepare": "Покуп+аем {what}..." 464 | } 465 | ... 466 | } 467 | ] 468 | 469 | С кнопками тоже самое, что и с сообщениями: 470 | 471 | [ 472 | { 473 | "question": ["купить", "приобрести"], 474 | "prepare": ["купить {what}", "приобрести {what}"], 475 | "send": { 476 | "message": { 477 | "question": "Покупаем...", 478 | "prepare": "Покупаем {what}..." 479 | }, 480 | "tts": { 481 | "question": "Покуп+аем...", 482 | "prepare": "Покуп+аем {what}..." 483 | }, 484 | "buttons": { 485 | "prepare": [ 486 | { 487 | "title": "ButtonPrepare1", 488 | "hide": false, 489 | "payload": [], 490 | "url": null 491 | }, 492 | { 493 | "title": "ButtonPrepare2", 494 | "hide": false, 495 | "payload": [], 496 | "url": null 497 | } 498 | ], 499 | "question": { 500 | "title": "ButtonQuestion1", 501 | "hide": false, 502 | "payload": [], 503 | "url": null 504 | } 505 | } 506 | } 507 | ] 508 | 509 | Как видите, помимо того, что можно добавить кнопку под каждый ответ, так их можно создать несколько. Это очень удобно и делает в два счета, да куда быстрее чем писать код. 510 | 511 | #### Пример кода с кнопками и payload: 512 | Payload - это аналог Callback на других сервисах. 513 | 514 | 515 | ..., 516 | "buttons": { 517 | "title": "ButtonPrepare1", 518 | "hide": false, 519 | "payload": { 520 | "function": "test", 521 | "vars": [ 522 | { 523 | "function": "test", 524 | "vars": {} 525 | } 526 | ] 527 | }, 528 | "url": null 529 | }, 530 | ... 531 | 532 | Аргументы из payload: 533 | 534 | |Аргумент|Тип данных|Описание| 535 | |--|--|-- 536 | |function|String|Функция, которая указана в payload.json. Настройка действия делается в этом файле. 537 | |vars|Array|Дополнительные переменные, которые будут переданы. Если вы использовали подготовленные запросы, то все переменные будут переданы **во все vars** кнопок, которые будут созданы. 538 | 539 | **ВНИМАНИЕ** 540 | Если указать несколько payload, то отправка кнопок или сообщений не будет, но вы можете таким образом обрабатывать различную информацию. Например, произвести оплату. 541 | 542 | #### Пример сложного JSON-блока: 543 | 544 | [ 545 | { 546 | "question": ["купить", "приобрести"], 547 | "prepare": ["купить {what}", "приобрести {what}"], 548 | "send": { 549 | "message": { 550 | "question": [ 551 | "Производим покупку...", 552 | "Покупаем...", 553 | "Оплачиваем..." 554 | ], 555 | "prepare": [ 556 | "Покупаем {what}...", 557 | "Приобретаем {what}..." 558 | ] 559 | }, 560 | "tts": { 561 | "question": [ 562 | "Произв+одим пок+упку...", 563 | "Покуп+аем...", 564 | "Опл+ачиваем..." 565 | ], 566 | "prepare": [ 567 | "Покуп+аем {what}...", 568 | "Приобрет+аем {what}..." 569 | ] 570 | }, 571 | "buttons": { 572 | "prepare": [ 573 | { 574 | "title": "ButtonPrepare1", 575 | "hide": false, 576 | "payload": [ 577 | { 578 | "function": "test", 579 | "vars": { 580 | "admin": "yes", 581 | "age": 23 582 | } 583 | } 584 | ], 585 | "url": null 586 | }, 587 | { 588 | "title": "ButtonPrepare2", 589 | "hide": false, 590 | "payload": [], 591 | "url": "https://example.ru/" 592 | } 593 | ], 594 | "question": { 595 | "title": "ButtonQuestion1", 596 | "hide": true, 597 | "payload": [], 598 | "url": "https://example.ru/" 599 | } 600 | } 601 | }, 602 | "end_session": false 603 | } 604 | ] 605 | 606 | Глобальное описание всех переменных: 607 | 608 | |Аргумент|Тип данных|Описание| 609 | |--|--|-- 610 | |question|String\|Array|Принимает сообщения для обработки. Если использовать массив, то будет вариация того, что может написать пользователь. 611 | |prepare|String\|Array|Подготовленные запросы, которые можно использовать за место **question**. Если использовать массив, то будет вариация того, что может написать пользователь. 612 | |send|Array|Массив, который обрабатывает все действия. 613 | |message|String\|Array|Аргумент, который отправляет сообщение пользователю. Если это массив, то будет создана вариация ответов. Рекомендуется делать соответствие текстов с TTS, чтобы не было асинхронности речевого синтеза и текста. Также можно указать тип ответа и на какой аргумент prepare или question. 614 | |tts|String\|Array|Аргумент, который создает синтез речи для текста. Если это массив, то будет создана вариация ответов. Рекомендуется делать соответствие текстов с TTS, чтобы не было асинхронности речевого синтеза и текста. 615 | |buttons|Array|Создание кнопок. Можно указать тип ответа prepare или question, добавить несколько кнопок. 616 | |title|String|Название кнопки. 617 | |hide|Bool|Скрыть кнопку после нажатия. 618 | |payload|Array|Отправить payload-запрос. 619 | |function|String|Название функции в файле payload.json. 620 | |vars|Array|Переменные для передачи с payload-запросом. 621 | |url|String|Отправить по ссылки при нажатии на кнопку. 622 | |end_session|Bool|Завершить сессию. 623 | 624 | 625 | ### Описание Payload 626 | Payload файл необходим для обработки запросов отправленных с кнопок: 627 | #### Пример запроса: 628 | 629 | { 630 | { 631 | "buy": { 632 | "sendMessage": { 633 | "message": [ 634 | "Вы хотите купить $^what|asd$. Вы уверены?", 635 | "Вы приобритаете $what$. Вы уверены?" 636 | ], 637 | "tts": [ 638 | "Вы хотите купить $what$. Вы уверены?", 639 | "Вы приобритаете $what$. Вы уверены?" 640 | ] 641 | }, 642 | "sendButtons": [ 643 | { 644 | "title": "Да, уверен.", 645 | "hide": false, 646 | "payload": [ 647 | { 648 | "function": "yes_buy", 649 | "vars": {} 650 | } 651 | ], 652 | "url": null 653 | } 654 | ] 655 | } 656 | } 657 | Описание аргументов: 658 | 659 | |Аргумент|Тип данных|Описание| 660 | |--|--|-- 661 | |buy|String|Название функции, за место buy можно использовать любые другие слова. Это название нужно передавать в button => payload => function. 662 | |sendMessage|Array|Аргумент для отправки сообщения. 663 | |message|String\|Array|Отправить сообщение. Если это массив, то будет создана вариация сообщений. Рекомендуется делать соответствие текстов с TTS, чтобы не было асинхронности речевого синтеза и текста. 664 | |tts|String\|Array|Отправить синтез речи. Если это массив, то будет создана вариация сообщений. Рекомендуется делать соответствие текстов с TTS, чтобы не было асинхронности речевого синтеза и текста. 665 | |sendButton|Array|Отправляет кнопки. 666 | |title|String|Название кнопки. 667 | |hide|Bool|Скрыть кнопку после нажатия. 668 | |payload|Array|Выполнить Payload-запрос. 669 | |function|String|Название функции в payload.json. 670 | |vars|Array|Переменные для передачи с payload-запросом. 671 | |url|String|Отправить по ссылки при нажатии на кнопку. 672 | 673 | ### Форматирование текста: 674 | > \$param\$ - получить переменную из переменной vars. Например вы передали: Купить {what}. Значит в payload нужно указать \$what\$ 675 | 676 | >\$^param\$ - если стоит такой знак, значит это слово будет исправлено в случае допущенной ошибки. Например: Исправить {what}. В переменной what = (здровстуйте). На выходи мы получим исправленное слово => здравствуйте. 677 | 678 | >\$param1|param2\$ - условия ИЛИ. Если переменная param1 будет пуста, то выведет param2 и наоборот. 679 | ___ 680 | ## Консоль Алиса 681 | Консоль, которая на данный момент создана для загрузки изображения и просмотра уже загруженных. 682 | #### php alisa upload:get 683 | Возвращает все загруженные изображения. 684 | 685 | Images List 686 | 687 | =========== 688 | ID: 11 689 | ImageName: f3ccdd27d2000e3f 690 | ImageFile: 1.jpg 691 | ImageID: 1030494/88a816aaacf55838ade8 692 | =========== 693 | 694 | ... 695 | 696 | #### php alisa upload:file `` 697 | Загружает изображение из папку, которую вы установили методом `setImageDir()`. 698 | 699 | #### php alisa upload:url `` 700 | Загружает изображение с указной ссылки. 701 | 702 | ___ 703 | ## index.php 704 | Файл для запуска чат-бота. 705 | Вы также можете изменить название файла, однако необходимо указывать то, что приведено к примеру ниже: 706 | 707 | $main = new \yandex\alisa\Alisa(); 708 | $main->addStartMessage("Добро пожаловать")->setCaseSensitive(false)->listen(); 709 | 710 | ___ 711 | ## setting.yml 712 | Файл для настройки стандартных констант. 713 | 714 | skill-name: АлиВиксед 715 | skill-id: 354e2695-98b3-4951-be30-e7e2efff5868 716 | skill-token: AQAAAAAW2RNZAAT7o0Uw9ECNE0WFgqvKcoGUppc 717 | 718 | |Константа|Описание| 719 | |--|--| 720 | |skill-name|Название навыка. 721 | |skill-id|ID-навыка. 722 | |skill-token|OAuth-токен Dialogs для работы с изображениями. 723 | 724 | ## Локальный Webhook: 725 | Чтобы запустить локальный webhook необходимо пройти на [ngrko](https://ngrok.com/) и создать аккаунт. 726 | После скачать программу и кинуть ее в удобно для вас место. 727 | Запустите командную строку и пропишете: 728 | ngrok http `port` 729 | Если это локальный сайт, то можете написать ngrok http `example.ru:port` 730 | В случае, если вы используете [OpenServer](https://ospanel.io/) , то необходимо еще указать алису в настройках: 731 | ![enter image description here](http://dl4.joxi.net/drive/2018/08/02/0024/0050/1622066/66/f83b666c74.png) 732 | При успешном запуске, просто введите этот адрес в Webhook URL: 733 | ![enter image description here](http://dl4.joxi.net/drive/2018/08/02/0024/0050/1622066/66/b5e67d7a60.png) 734 | 735 | ___ 736 | Version: 2.1 737 | Danil Sidorenko © MIT 2018 738 | -------------------------------------------------------------------------------- /alisa: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | findAll())+1; 12 | 13 | if( strstr($argv[1], 'upload:file') ) { 14 | $result = $main->uploadImage($argv[2]); 15 | echo "\n\r===========\n\rSuccess Upload File"; 16 | echo "\n\rID: ".$result[$last]['id']."\n\r"; 17 | echo "ImageName: ".$result[$last]['image_name']."\n\r"; 18 | echo "ImageFile: ".$result[$last]['file_name']."\n\r"; 19 | echo "ImageID: ".$result[$last]['image_id']."\n\r===========\n\r"; 20 | 21 | } elseif( strstr($argv[1], "upload:url") ) { 22 | if( preg_match('/^((https|http)?:\/\/)?([\w\.]+)\.([a-z]{2,6}\.?)(\/[\w\.]*)*\/.*$/', $argv[2]) ) { 23 | $result = $main->uploadImage($argv[2]); 24 | echo "\n\r===========\n\rSuccess Upload File as Url"; 25 | echo "\n\rID: ".$result[$last]['id']."\n\r"; 26 | echo "ImageName: ".$result[$last]['image_name']."\n\r"; 27 | echo "ImageFile: ".$result[$last]['file_name']."\n\r"; 28 | echo "ImageID: ".$result[$last]['image_id']."\n\r===========\n\r"; 29 | 30 | } else { 31 | die("\n\r==============\n\rYou must use the link as you want to upload the image from other sources.\n\r==============\n\r"); 32 | } 33 | } elseif( strstr($argv[1], "upload:get") ) { 34 | $images = DB::table('images')->findAll()->asArray(); 35 | echo "\n\r===========\n\rImages List"; 36 | foreach ($images as $key=>$val) { 37 | echo "\n\rID: ".$images[$key]['id']."\n\r"; 38 | echo "ImageName: ".$images[$key]['image_name']."\n\r"; 39 | echo "ImageFile: ".$images[$key]['file_name']."\n\r"; 40 | echo "ImageID: ".$images[$key]['image_id']."\n\r===========\n\r\n\r"; 41 | } 42 | } 43 | 44 | ?> -------------------------------------------------------------------------------- /blocks/actions.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "question": [ 4 | "купить", 5 | "приобрести" 6 | ], 7 | "prepare": [ 8 | "купить {what}", 9 | "приобрести {what}" 10 | ], 11 | "send": { 12 | "message": { 13 | "question": [ 14 | "Производим покупку...", 15 | "Покупаем...", 16 | "Оплачиваем..." 17 | ], 18 | "prepare": [ 19 | "Покупаем {what}...", 20 | "Приобретаем {what}..." 21 | ] 22 | }, 23 | "tts": { 24 | "question": [ 25 | "Произв+одим пок+упку...", 26 | "Покуп+аем...", 27 | "Опл+ачиваем..." 28 | ], 29 | "prepare": [ 30 | "Покуп+аем {what}...", 31 | "Приобрет+аем {what}..." 32 | ] 33 | }, 34 | "buttons": { 35 | "prepare": [ 36 | { 37 | "title": "ButtonPrepare1", 38 | "hide": false, 39 | "payload": [ 40 | { 41 | "function": "test", 42 | "vars": { 43 | "admin": "yes", 44 | "age": 23 45 | } 46 | } 47 | ], 48 | "url": null 49 | }, 50 | { 51 | "title": "ButtonPrepare2", 52 | "hide": false, 53 | "payload": [], 54 | "url": "https://example.ru/" 55 | } 56 | ], 57 | "question": { 58 | "title": "ButtonQuestion1", 59 | "hide": true, 60 | "payload": [], 61 | "url": "https://example.ru/" 62 | } 63 | } 64 | }, 65 | "end_session": false 66 | } 67 | ] -------------------------------------------------------------------------------- /blocks/payload.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": { 3 | "sendMessage": { 4 | "message": [ 5 | "Привет", 6 | "Дарова" 7 | ], 8 | "tts": [ 9 | "Привет", 10 | "Дарова" 11 | ] 12 | }, 13 | "sendButtons": [ 14 | { 15 | "title": "Привет1", 16 | "hide": false, 17 | "payload": [ 18 | { 19 | "function": "test2", 20 | "vars": {} 21 | } 22 | ], 23 | "url": null 24 | } 25 | ] 26 | } 27 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "danil005/php-yandex-alisa", 3 | "description": "PHP lib for alisa-bot", 4 | "type": "project", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Danil Sidorenko", 9 | "email": "danilsidorenko98@mail.ru" 10 | } 11 | ], 12 | "version": "2.1", 13 | "minimum-stability": "dev", 14 | "autoload": { 15 | "psr-4": { 16 | "yandex\\alisa\\": "src/" 17 | } 18 | }, 19 | "require": { 20 | "php": ">=7.0", 21 | "league/flysystem": "^1.0", 22 | "romaricdrigon/metayaml": "^1.1", 23 | "greg0/lazer-database": "^1.1" 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "76207bdf34d4a7ccef20b8789202a5e7", 8 | "packages": [ 9 | { 10 | "name": "greg0/lazer-database", 11 | "version": "1.1.4", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/Greg0/Lazer-Database.git", 15 | "reference": "201296de3f5f8d4ac7a6dd8cbdaf2dc3402e2f09" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/Greg0/Lazer-Database/zipball/201296de3f5f8d4ac7a6dd8cbdaf2dc3402e2f09", 20 | "reference": "201296de3f5f8d4ac7a6dd8cbdaf2dc3402e2f09", 21 | "shasum": "" 22 | }, 23 | "require": { 24 | "php": ">=5.6" 25 | }, 26 | "require-dev": { 27 | "mikey179/vfsstream": "~1.6", 28 | "phpunit/phpunit": "^5.6" 29 | }, 30 | "type": "library", 31 | "autoload": { 32 | "psr-4": { 33 | "Lazer\\": "src/", 34 | "Lazer\\Test\\": "tests/src/" 35 | } 36 | }, 37 | "notification-url": "https://packagist.org/downloads/", 38 | "license": [ 39 | "MIT" 40 | ], 41 | "authors": [ 42 | { 43 | "name": "Grzegorz Kuźnik", 44 | "email": "gerg0sz92@gmail.com" 45 | } 46 | ], 47 | "description": "PHP library to use JSON files like flat-file database", 48 | "homepage": "https://github.com/Greg0/Lazer-Database", 49 | "keywords": [ 50 | "Simple", 51 | "database", 52 | "db", 53 | "file", 54 | "flat", 55 | "json", 56 | "lazer" 57 | ], 58 | "time": "2018-05-24T08:11:44+00:00" 59 | }, 60 | { 61 | "name": "league/flysystem", 62 | "version": "1.0.45", 63 | "source": { 64 | "type": "git", 65 | "url": "https://github.com/thephpleague/flysystem.git", 66 | "reference": "a99f94e63b512d75f851b181afcdf0ee9ebef7e6" 67 | }, 68 | "dist": { 69 | "type": "zip", 70 | "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a99f94e63b512d75f851b181afcdf0ee9ebef7e6", 71 | "reference": "a99f94e63b512d75f851b181afcdf0ee9ebef7e6", 72 | "shasum": "" 73 | }, 74 | "require": { 75 | "php": ">=5.5.9" 76 | }, 77 | "conflict": { 78 | "league/flysystem-sftp": "<1.0.6" 79 | }, 80 | "require-dev": { 81 | "ext-fileinfo": "*", 82 | "phpspec/phpspec": "^3.4", 83 | "phpunit/phpunit": "^5.7" 84 | }, 85 | "suggest": { 86 | "ext-fileinfo": "Required for MimeType", 87 | "ext-ftp": "Allows you to use FTP server storage", 88 | "ext-openssl": "Allows you to use FTPS server storage", 89 | "league/flysystem-aws-s3-v2": "Allows you to use S3 storage with AWS SDK v2", 90 | "league/flysystem-aws-s3-v3": "Allows you to use S3 storage with AWS SDK v3", 91 | "league/flysystem-azure": "Allows you to use Windows Azure Blob storage", 92 | "league/flysystem-cached-adapter": "Flysystem adapter decorator for metadata caching", 93 | "league/flysystem-eventable-filesystem": "Allows you to use EventableFilesystem", 94 | "league/flysystem-rackspace": "Allows you to use Rackspace Cloud Files", 95 | "league/flysystem-sftp": "Allows you to use SFTP server storage via phpseclib", 96 | "league/flysystem-webdav": "Allows you to use WebDAV storage", 97 | "league/flysystem-ziparchive": "Allows you to use ZipArchive adapter", 98 | "spatie/flysystem-dropbox": "Allows you to use Dropbox storage", 99 | "srmklive/flysystem-dropbox-v2": "Allows you to use Dropbox storage for PHP 5 applications" 100 | }, 101 | "type": "library", 102 | "extra": { 103 | "branch-alias": { 104 | "dev-master": "1.1-dev" 105 | } 106 | }, 107 | "autoload": { 108 | "psr-4": { 109 | "League\\Flysystem\\": "src/" 110 | } 111 | }, 112 | "notification-url": "https://packagist.org/downloads/", 113 | "license": [ 114 | "MIT" 115 | ], 116 | "authors": [ 117 | { 118 | "name": "Frank de Jonge", 119 | "email": "info@frenky.net" 120 | } 121 | ], 122 | "description": "Filesystem abstraction: Many filesystems, one API.", 123 | "keywords": [ 124 | "Cloud Files", 125 | "WebDAV", 126 | "abstraction", 127 | "aws", 128 | "cloud", 129 | "copy.com", 130 | "dropbox", 131 | "file systems", 132 | "files", 133 | "filesystem", 134 | "filesystems", 135 | "ftp", 136 | "rackspace", 137 | "remote", 138 | "s3", 139 | "sftp", 140 | "storage" 141 | ], 142 | "time": "2018-05-07T08:44:23+00:00" 143 | }, 144 | { 145 | "name": "romaricdrigon/metayaml", 146 | "version": "1.1", 147 | "source": { 148 | "type": "git", 149 | "url": "https://github.com/romaricdrigon/MetaYaml.git", 150 | "reference": "03b0af567981a8a060606989c395974baf385bd1" 151 | }, 152 | "dist": { 153 | "type": "zip", 154 | "url": "https://api.github.com/repos/romaricdrigon/MetaYaml/zipball/03b0af567981a8a060606989c395974baf385bd1", 155 | "reference": "03b0af567981a8a060606989c395974baf385bd1", 156 | "shasum": "" 157 | }, 158 | "require": { 159 | "php": ">=5.3.3", 160 | "symfony/yaml": "~2.3|~3.0" 161 | }, 162 | "require-dev": { 163 | "atoum/atoum": "~1" 164 | }, 165 | "type": "library", 166 | "autoload": { 167 | "psr-0": { 168 | "RomaricDrigon\\MetaYaml": "src/" 169 | } 170 | }, 171 | "notification-url": "https://packagist.org/downloads/", 172 | "license": [ 173 | "MIT" 174 | ], 175 | "description": "Using [Yaml|Xml|json] schemas files to validate [Yaml|Xml|json] ", 176 | "homepage": "http://github.com/romaricdrigon/MetaYaml", 177 | "keywords": [ 178 | "json", 179 | "schema", 180 | "validation", 181 | "xml", 182 | "yaml" 183 | ], 184 | "time": "2016-02-29T10:28:30+00:00" 185 | }, 186 | { 187 | "name": "symfony/polyfill-ctype", 188 | "version": "v1.9.0", 189 | "source": { 190 | "type": "git", 191 | "url": "https://github.com/symfony/polyfill-ctype.git", 192 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" 193 | }, 194 | "dist": { 195 | "type": "zip", 196 | "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", 197 | "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", 198 | "shasum": "" 199 | }, 200 | "require": { 201 | "php": ">=5.3.3" 202 | }, 203 | "suggest": { 204 | "ext-ctype": "For best performance" 205 | }, 206 | "type": "library", 207 | "extra": { 208 | "branch-alias": { 209 | "dev-master": "1.9-dev" 210 | } 211 | }, 212 | "autoload": { 213 | "psr-4": { 214 | "Symfony\\Polyfill\\Ctype\\": "" 215 | }, 216 | "files": [ 217 | "bootstrap.php" 218 | ] 219 | }, 220 | "notification-url": "https://packagist.org/downloads/", 221 | "license": [ 222 | "MIT" 223 | ], 224 | "authors": [ 225 | { 226 | "name": "Symfony Community", 227 | "homepage": "https://symfony.com/contributors" 228 | }, 229 | { 230 | "name": "Gert de Pagter", 231 | "email": "BackEndTea@gmail.com" 232 | } 233 | ], 234 | "description": "Symfony polyfill for ctype functions", 235 | "homepage": "https://symfony.com", 236 | "keywords": [ 237 | "compatibility", 238 | "ctype", 239 | "polyfill", 240 | "portable" 241 | ], 242 | "time": "2018-08-06T14:22:27+00:00" 243 | }, 244 | { 245 | "name": "symfony/yaml", 246 | "version": "v3.4.14", 247 | "source": { 248 | "type": "git", 249 | "url": "https://github.com/symfony/yaml.git", 250 | "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2" 251 | }, 252 | "dist": { 253 | "type": "zip", 254 | "url": "https://api.github.com/repos/symfony/yaml/zipball/810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", 255 | "reference": "810af2d35fc72b6cf5c01116806d2b65ccaaf2e2", 256 | "shasum": "" 257 | }, 258 | "require": { 259 | "php": "^5.5.9|>=7.0.8", 260 | "symfony/polyfill-ctype": "~1.8" 261 | }, 262 | "conflict": { 263 | "symfony/console": "<3.4" 264 | }, 265 | "require-dev": { 266 | "symfony/console": "~3.4|~4.0" 267 | }, 268 | "suggest": { 269 | "symfony/console": "For validating YAML files using the lint command" 270 | }, 271 | "type": "library", 272 | "extra": { 273 | "branch-alias": { 274 | "dev-master": "3.4-dev" 275 | } 276 | }, 277 | "autoload": { 278 | "psr-4": { 279 | "Symfony\\Component\\Yaml\\": "" 280 | }, 281 | "exclude-from-classmap": [ 282 | "/Tests/" 283 | ] 284 | }, 285 | "notification-url": "https://packagist.org/downloads/", 286 | "license": [ 287 | "MIT" 288 | ], 289 | "authors": [ 290 | { 291 | "name": "Fabien Potencier", 292 | "email": "fabien@symfony.com" 293 | }, 294 | { 295 | "name": "Symfony Community", 296 | "homepage": "https://symfony.com/contributors" 297 | } 298 | ], 299 | "description": "Symfony Yaml Component", 300 | "homepage": "https://symfony.com", 301 | "time": "2018-07-26T11:19:56+00:00" 302 | } 303 | ], 304 | "packages-dev": [], 305 | "aliases": [], 306 | "minimum-stability": "alpha", 307 | "stability-flags": [], 308 | "prefer-stable": false, 309 | "prefer-lowest": false, 310 | "platform": { 311 | "php": ">=7.0" 312 | }, 313 | "platform-dev": [] 314 | } 315 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | addStartMessage($messageStart) 7 | ->setCaseSensitive(false) 8 | ->setBlocksActions(false) 9 | ->setSpellerCorrect(true) 10 | ->listen(); 11 | -------------------------------------------------------------------------------- /settings.yml: -------------------------------------------------------------------------------- 1 | # Файл конфигурации 2 | # 3 | # skill-name - название навыка 4 | # skill-id - ID-навыка 5 | # skill-token - токен для авторизации. 6 | 7 | 8 | skill-name: АлиВиксед 9 | skill-id: 354e2695-98b3-4951-be30-e7e2efff5868 10 | skill-token: AQAAAAAW2RNZAAT7o0Uw9ECNE0WFgqvKcoGUppc -------------------------------------------------------------------------------- /src/Alisa.php: -------------------------------------------------------------------------------- 1 | blocks == true ) { 89 | return $this->executeBlockSystem($command); 90 | } 91 | if( $command == "привет" ) { 92 | $this->sendGallery([ 93 | [ 94 | "file"=>'1.jpg', 95 | 'title'=>'Текст', 96 | 'desc'=>"Описание.", 97 | "options"=>[ 98 | 'message'=>"Тест", 99 | 'payload'=>[ 100 | "function"=>1 101 | ] 102 | ] 103 | ], 104 | [ 105 | "file"=>'2.jpg', 106 | 'title'=>'Текст', 107 | 'desc'=>"Описание.", 108 | "options"=>[ 109 | 'message'=>"Тест", 110 | 'payload'=>[ 111 | "function"=>1 112 | ] 113 | ] 114 | ] 115 | ], 'Тест', 'Привет', [ 116 | 'payload'=>[ 117 | 'function'=>"test" 118 | ] 119 | ]); 120 | } 121 | return false; 122 | } 123 | 124 | /** 125 | * Выполнить дополнительные функции Payload. 126 | * @param array $callback 127 | * 128 | * @return bool 129 | */ 130 | public function payload(Array $callback) { 131 | if( $this->blocks == true ) { 132 | return $this->executePayload($callback); 133 | } 134 | return false; 135 | } 136 | 137 | /** 138 | * @param $on 139 | * 140 | * @return $this 141 | */ 142 | public function setBlocksActions(bool $on = true) { 143 | $this->blocks = $on; 144 | return $this; 145 | } 146 | 147 | /** 148 | * Установить директорию изображений. 149 | * @param String $path 150 | * 151 | * @return $this 152 | */ 153 | public function setImagesDir(String $path) { 154 | $this->imagesDir = $path; 155 | return $this; 156 | } 157 | 158 | /** 159 | * Установить проверку на орфографию. 160 | * @param bool $speller 161 | * 162 | * @return $this 163 | */ 164 | public function setSpellerCorrect(bool $speller = false) { 165 | $this->speller = $speller; 166 | return $this; 167 | } 168 | 169 | /** 170 | * Установить чувствительность к регистру. 171 | * @param bool $sensitive 172 | * 173 | * @return $this 174 | */ 175 | public function setCaseSensitive(bool $sensitive = true) { 176 | $this->caseSensitive = $sensitive; 177 | return $this; 178 | } 179 | 180 | /** 181 | * Установить значение по умолчанию, если чат-бот не смог понять, 182 | * что от него хотят. 183 | * 184 | * @param String $message 185 | * 186 | * @return string 187 | */ 188 | public function setAny(String $message) { 189 | $this->anyMessage = $message; 190 | return $this; 191 | } 192 | 193 | /** 194 | * Установить стартовое сообщение. 195 | * @param String $message 196 | * 197 | * @return $this 198 | */ 199 | public function addStartMessage(String $message) { 200 | $this->startMessage = $message; 201 | if( empty($this->startMessageTTS) ) { 202 | $this->startMessageTTS = $message; 203 | } 204 | return $this; 205 | } 206 | 207 | /** 208 | * Установить стартовое TTS-сообщение (синтез речи). 209 | * @param String $message 210 | * 211 | * @return $this 212 | */ 213 | public function addStartTTS(String $message) { 214 | $this->startMessageTTS = $message; 215 | return $this; 216 | } 217 | 218 | /** 219 | * Установить кнопку, которая будут отображаться при старте навыка. 220 | * 221 | * @param String $title - название кнопки 222 | * @param bool $hide - скрыть после нажатия. По умолчанию: false 223 | * @param array $payload - дополнительные данные, которые нужно отправить. По умолчанию: пустой массив 224 | * @param String $url - ссылка на сайт. По умолчанию: null 225 | * 226 | * @return $this 227 | */ 228 | public function addStartButton(String $title, bool $hide = false, Array $payload = [], String $url = null) { 229 | $this->startButton[] = [ 230 | 'title'=>$title, 231 | 'payload'=>$payload, 232 | 'url'=>$url, 233 | 'hide'=>$hide 234 | ]; 235 | return $this; 236 | } 237 | 238 | /** 239 | * Метод для установки версии Алисы. 240 | * @param String $version 241 | * 242 | * @return $this 243 | */ 244 | public function setVersion(String $version = self::VERSION) { 245 | $this->version = $version; 246 | return $this; 247 | } 248 | 249 | public function addButton(String $title, bool $hide = false, Array $payload = [], String $url = null) { 250 | $this->response['response']['buttons'][] = [ 251 | 'title'=>$title, 252 | 'payload'=>$payload, 253 | 'url'=>$url, 254 | 'hide'=>$hide 255 | ]; 256 | return $this; 257 | } 258 | 259 | /** 260 | * Завершить сессию и закрыть навык. 261 | * @return bool 262 | */ 263 | public function setEndMessage() { 264 | $this->response['response']['end_session'] = true; 265 | return true; 266 | } 267 | 268 | /** 269 | * Отправить сообщению пользователю. 270 | * @param String $message 271 | * @param String $tts 272 | * @param bool $speller 273 | * 274 | * @return $this 275 | */ 276 | public function sendMessage(String $message, String $tts = "", bool $speller = false) { 277 | $msg = ( $speller == true ) ? $this->spellingCheck($message) : $message; 278 | $this->response = [ 279 | 'response' => [ 280 | 'text' => $msg, 281 | 'tts' => $tts, 282 | 'end_session' => false 283 | ] 284 | ]; 285 | return $this; 286 | } 287 | 288 | /** 289 | * Отправить галерею. 290 | * @param array $images 291 | * @param String $headerText 292 | * @param String $footerText 293 | * @param array $footerOpt 294 | * 295 | * @return $this 296 | */ 297 | public function sendGallery(Array $images, String $headerText = "", String $footerText = "", Array $footerOpt = []) { 298 | $img = DB::table('images')->findAll()->asArray(); 299 | $items = []; 300 | $this->response['response']['card'] = [ 301 | "type" => "ItemsList" 302 | ]; 303 | 304 | if( $headerText != "" ) { 305 | $this->response['response']['card']['header'] = ["text"=>$headerText]; 306 | } 307 | foreach ($img as $image) { 308 | foreach ($images as $k=>$value) { 309 | if ( $image['image_name'] == substr( md5( $value['file'] ), 0, 16 ) ) { 310 | $i[$k] = [ 311 | "image_id" => $image['image_id'], 312 | "title" => $value['title'], 313 | "description" => $value['desc'], 314 | ]; 315 | if( $value['options']['url'] != "" ) { 316 | $i[$k]["button"]['url'] = $value['options']['url']; 317 | } 318 | if( $value['options']['payload'] != "" ) { 319 | $i[$k]["button"]['payload'] = $value['options']['payload']; 320 | } 321 | if( $value['options']['message'] != "" ) { 322 | $i[$k]["button"]['text'] = $value['options']['message']; 323 | } 324 | $items['items'] = $i; 325 | $paths[] = substr( md5( $value['file'] ), 0, 16 ); 326 | } 327 | } 328 | } 329 | 330 | $this->response['response']['card'] = array_merge($this->response['response']['card'], $items); 331 | if( $footerText != "" ) $this->response['response']['card']['footer'] = ["text"=>$footerText]; 332 | if( $footerOpt != [] ) $this->response['response']['card']['footer'] = ["button"=>["url"=>$footerOpt['url'], "payload"=>$footerOpt['payload']]]; 333 | return $this; 334 | } 335 | 336 | /** 337 | * Отправить изображение. 338 | * @param $path 339 | * @param string $title 340 | * @param string $description 341 | * @param array $options 342 | * 343 | * @return $this 344 | */ 345 | public function sendImage($path, String $title = "", String $description = "", Array $options = []) { 346 | $img = DB::table('images')->findAll()->asArray(); 347 | foreach ($img as $key=>$value) { 348 | if( $value['image_name'] == substr(md5($path), 0, 16) ) { 349 | $this->response['response']['card'] =[ 350 | "type" => "BigImage", 351 | "image_id" => $value['image_id'], 352 | "title" => $title, 353 | "description" => $description 354 | ]; 355 | if( $options != [] ) { 356 | $this->response['response']['card']['button'] = ['url'=>$options['url'], 'payload'=>$options['payload']]; 357 | } 358 | return $this; 359 | } 360 | } 361 | $mPath = substr(md5($path), 0, 16); 362 | die("[ALISA]: Image \"{$mPath}\" not found. [Original: {$path}]"); 363 | } 364 | 365 | /** 366 | * Запись пришедших данных в текстовый файл. 367 | * 368 | * @param String $data 369 | */ 370 | private function logger(String $data = "") { 371 | if (!empty($this->request)) { 372 | if ($data == "") { 373 | $s = $this->request; 374 | } else { 375 | $s = $data; 376 | } 377 | file_put_contents( 378 | 'alisa_log.txt', 379 | date('Y-m-d H:i:s') . 380 | PHP_EOL . $s . PHP_EOL, 381 | FILE_APPEND 382 | ); 383 | } 384 | } 385 | protected function sendPayload(String $message, String $tts = "", array $button = []) { 386 | $this->sendMessage($message, $tts)->addButton($button['title'], $button['hide'], $button['payload'], $button['url']); 387 | unset($this->request['request']['payload']); 388 | } 389 | 390 | 391 | /** 392 | * Вывести переменные. 393 | * @param String $message 394 | * 395 | * @return mixed|String 396 | */ 397 | public function printVars(String $message) { 398 | $words = explode(" ", $message); 399 | foreach ($words as $key => $value) { 400 | if (strstr($value, '{') && strstr($value, '}')) { 401 | $index = substr(strstr($value, '{'), 1,strpos($value, '}') - 1); 402 | if( array_key_exists($index, $this->vars) ) { 403 | $message = str_replace("{" . $index . "}", $this->vars[$index], $message); 404 | } else { 405 | die("[JSON_BLOCKS#3] Fatal Error: vars {".$index."} not found."); 406 | } 407 | } 408 | } 409 | 410 | return $message; 411 | } 412 | 413 | 414 | /** 415 | * Прослушивать все запросы, которые приходят на сервер. 416 | * 417 | * @return bool|null 418 | */ 419 | public function listen() { 420 | $this->request = json_decode(file_get_contents('php://input'), true); 421 | header('Content-Type: application/json'); 422 | if( isset( 423 | $this->request['request'], 424 | $this->request['request']['command'], 425 | $this->request['session'], 426 | $this->request['session']['session_id'], 427 | $this->request['session']['message_id'], 428 | $this->request['session']['user_id'] 429 | ) ) { 430 | $this->logger(); 431 | 432 | if( $this->speller == true ) { 433 | $this->request['request']['command'] = $this->spellingCheck($this->request['request']['command']); 434 | } 435 | 436 | if ( $this->request['request']['command'] == "" ) { 437 | $this->response = [ 438 | 'response' => [ 439 | 'text' => $this->startMessage, 440 | 'tts' => $this->startMessageTTS, 441 | 'buttons' => $this->startButton, 442 | 'end_session' => false 443 | ] 444 | ]; 445 | } else { 446 | if( $this->caseSensitive == true ) { 447 | $command = $this->request['request']['command']; 448 | } else { 449 | $command = mb_strtolower($this->request['request']['command']); 450 | } 451 | if ( !$this->cmd($command) ) { 452 | $this->response['response']['text'] = $this->anyMessage; 453 | }; 454 | } 455 | 456 | $this->response = array_merge($this->response, 457 | [ 458 | 'session' => [ 459 | 'session_id' => $this->request['session']['session_id'], 460 | 'message_id' => $this->request['session']['message_id'], 461 | 'user_id' => $this->request['session']['user_id'] 462 | ], 463 | 'version' => "{$this->version}" 464 | ] 465 | ); 466 | echo json_encode($this->response); 467 | return true; 468 | } elseif( $this->request['request']['type'] == "ButtonPressed" ) { 469 | $this->response = []; 470 | if ( !$this->payload($this->request['request']['payload']) ) { 471 | $this->response['response']['text'] = $this->anyMessage; 472 | }; 473 | 474 | $this->response = array_merge($this->response, 475 | [ 476 | 'session' => [ 477 | 'session_id' => $this->request['session']['session_id'], 478 | 'message_id' => $this->request['session']['message_id'], 479 | 'user_id' => $this->request['session']['user_id'] 480 | ], 481 | 'version' => "{$this->version}" 482 | ] 483 | ); 484 | echo json_encode($this->response); 485 | return true; 486 | } else { 487 | echo $this->response = json_encode([]); 488 | return false; 489 | } 490 | } 491 | } -------------------------------------------------------------------------------- /src/database/images.config.json: -------------------------------------------------------------------------------- 1 | {"last_id":13,"schema":{"id":"integer","image_name":"string","image_id":"string","file_name":"string"},"relations":{}} -------------------------------------------------------------------------------- /src/database/images.data.json: -------------------------------------------------------------------------------- 1 | [{"id":11,"image_name":"f3ccdd27d2000e3f","image_id":"1030494\/88a816aaacf55838ade8","file_name":"1.jpg"},{"id":12,"image_name":"156005c5baf40ff5","image_id":"965417\/9d6d5b9dab3511360fb4","file_name":"2.jpg"},{"id":13,"image_name":"156005c5baf40ff5","image_id":"965417\/970556ebc36bf7d2af49","file_name":"2.jpg"}] -------------------------------------------------------------------------------- /src/handler.php: -------------------------------------------------------------------------------- 1 | files = new Filesystem(new Local(__DIR__ . "../../blocks"), ['visibility' => 'public']); 64 | $loader = new YamlLoader(); 65 | $setting = $loader->loadFromFile('settings.yml'); 66 | $this->token = $setting['skill-token']; 67 | $this->skillID = $setting['skill-id']; 68 | $this->skillName = $setting['skill-name']; 69 | } 70 | 71 | 72 | /** 73 | * Вариация вопросов. 74 | * @param array $list 75 | * @param String $command 76 | * 77 | * @return bool 78 | */ 79 | protected function optionsQuestions(Array $list, String $command) { 80 | foreach ($list as $options) { 81 | if( $command == $options ) return true; 82 | } 83 | return false; 84 | } 85 | 86 | /** 87 | * Вариация ответов. 88 | * @param array $list 89 | * @param int $type 90 | * 91 | * @return mixed|int 92 | */ 93 | protected function optionsAnswers(Array $list, int $type = 0) { 94 | if( $type == 0 ) { 95 | $randomMessage = $list[ rand( 0, count( $list ) - 1 ) ]; 96 | 97 | return $randomMessage; 98 | } else { 99 | return rand( 0, count( $list ) - 1); 100 | } 101 | } 102 | 103 | /** 104 | * Опциональный выбор Callback (Операция ИЛИ) 105 | * @param array $list 106 | * @param array $callback 107 | * 108 | * @return bool 109 | */ 110 | protected function optionsCallback(Array $list, Array $callback) { 111 | foreach ($list as $options) { 112 | foreach ($callback as $name=>$value) { 113 | if( $options == $name ) return true; 114 | } 115 | } 116 | return false; 117 | } 118 | 119 | /** 120 | * Подготовленные запросы. 121 | * @param $getMessage 122 | * @param String $command 123 | * 124 | * @return bool 125 | */ 126 | protected function prepare($getMessage, String $command) { 127 | $var = []; $math = ""; 128 | if( !is_array($getMessage) ) { 129 | $words = explode(" ", $getMessage); 130 | $wordsCommand = explode(" ", $command); 131 | 132 | 133 | $s = array_diff($wordsCommand, $words); 134 | 135 | foreach ($words as $key => $value) { 136 | if (strstr($value, '{') && strstr($value, '}')) { 137 | $index = substr(strstr($value, '{'), 1,strpos($value, '}') - 1); 138 | $var[$index] = $s[$key]; 139 | $words[$key] = ".*"; 140 | } 141 | } 142 | foreach ($words as $key=>$value) { 143 | if( array_key_exists($key+1, $words) ) { 144 | $math .= $value. " "; 145 | } else { 146 | $math .= $value. ""; 147 | } 148 | } 149 | $math = "/".$math."/"; 150 | if( preg_match($math, $command) ) { 151 | $this->vars = $var; 152 | return true; 153 | } 154 | } else { 155 | foreach ($getMessage as $k=>$msg) { 156 | $math = ""; 157 | $words = explode(" ", $msg); 158 | $wordsCommand = explode(" ", $command); 159 | 160 | 161 | $s = array_diff($wordsCommand, $words); 162 | 163 | foreach ($words as $key => $value) { 164 | if (strstr($value, '{') && strstr($value, '}')) { 165 | $index = substr(strstr($value, '{'), 1,strpos($value, '}') - 1); 166 | $var[$index] = $s[$key]; 167 | $words[$key] = ".*"; 168 | } 169 | } 170 | foreach ($words as $key=>$value) { 171 | if( array_key_exists($key+1, $words) ) { 172 | $math .= $value. " "; 173 | } else { 174 | $math .= $value. ""; 175 | } 176 | } 177 | $math = "/".$math."/"; 178 | if( preg_match($math, $command) ) { 179 | $this->vars = $var; 180 | return true; 181 | } else { 182 | continue; 183 | } 184 | } 185 | } 186 | return false; 187 | } 188 | 189 | /** 190 | * Преобразовывает объект в массив. 191 | * @param $d 192 | * 193 | * @return array|Object 194 | */ 195 | public function objectToArray($d) { 196 | return json_decode(json_encode(json_decode($d)), true); 197 | } 198 | 199 | 200 | /** 201 | * Проверка на орфографию и исправление. 202 | * @param String $message 203 | * 204 | * @return mixed|String 205 | */ 206 | protected function spellingCheck(String $message) { 207 | $ch = curl_init(); 208 | $options = [ 209 | CURLOPT_URL => "https://speller.yandex.net/services/spellservice.json/checkText", 210 | CURLOPT_POST => TRUE, 211 | CURLOPT_POSTFIELDS => "text=".$message."&format=html&lang=ru", 212 | CURLOPT_RETURNTRANSFER => TRUE 213 | ]; 214 | curl_setopt_array($ch, $options); 215 | $r=$this->objectToArray(curl_exec($ch)); 216 | 217 | if (curl_errno($ch)) { 218 | echo curl_error($ch)."\n"; 219 | } 220 | curl_close($ch); 221 | foreach ($r as $value) { 222 | $word = $value['word']; 223 | $change = $value['s'][0]; 224 | $message = str_replace($word, $change, $message); 225 | } 226 | return $message; 227 | } 228 | 229 | /** 230 | * Загрузить изображение. 231 | * @param $path 232 | * 233 | * @return mixed 234 | */ 235 | public function uploadImage($path) { 236 | $id = $this->curlImage($this->imagesDir . '/'. $path)['image']['id']; 237 | $image = DB::table('images'); 238 | $image->image_name = substr(md5($path), 0, 16); 239 | $image->image_id = $id; 240 | $image->file_name = pathinfo($path)['basename']; 241 | $image->save(); 242 | return $image->find()->asArray(); 243 | } 244 | 245 | /** 246 | * Curl запрос 247 | * @param string $path 248 | * 249 | * @return array|Object 250 | */ 251 | public function curlImage($path = "") { 252 | $ch = curl_init(); 253 | $options = [ 254 | CURLOPT_URL => "https://dialogs.yandex.net/api/v1/skills/".$this->skillID."/images", 255 | CURLOPT_POST => FALSE, 256 | CURLOPT_HTTPHEADER => [ 257 | "Authorization: OAuth {$this->token}", 258 | ], 259 | CURLOPT_RETURNTRANSFER => true 260 | ]; 261 | 262 | if( preg_match('/^((https|http)?:\/\/)?([\w\.]+)\.([a-z]{2,6}\.?)(\/[\w\.]*)*\/.*$/', $path) ) { 263 | $options[CURLOPT_POST] = true; 264 | $options[CURLOPT_POSTFIELDS] = [ 265 | "url"=>$path 266 | ]; 267 | } elseif( $path != "" ) { 268 | array_push($options, "Content-Type: multipart/form-data"); 269 | $options[CURLOPT_POST] = true; 270 | $file = new \CURLFile(__DIR__ . '../../'.$path); 271 | $options[CURLOPT_POSTFIELDS] = ["file"=>$file]; 272 | } 273 | 274 | curl_setopt_array( $ch, $options ); 275 | $r = $this->objectToArray(curl_exec( $ch )); 276 | if ( curl_errno( $ch ) ) { 277 | echo curl_error( $ch ) . "\n"; 278 | } 279 | curl_close( $ch ); 280 | return $r; 281 | } 282 | 283 | /** 284 | * Файловая система. 285 | * 286 | * @param $path 287 | * 288 | * @return \League\Flysystem\Filesystem 289 | */ 290 | public function read($path) { 291 | return $this->files->read($path); 292 | } 293 | } -------------------------------------------------------------------------------- /src/traits/SBlock.php: -------------------------------------------------------------------------------- 1 | "question or prepare method not found", 19 | 2=>"sent method not found", 20 | 3=>"method for button not found", 21 | 4=>"this function ({function}) wasn't found", 22 | 5=>"var \"{input}\" not found from varsToPayload" 23 | ]; 24 | 25 | /** 26 | * Построение ошибки JSON-блоков. 27 | * @param int $error 28 | * @param array $input 29 | * 30 | * @return string 31 | */ 32 | private function errorMessage(int $error, array $input = []) { 33 | if( $input != "" ) { 34 | foreach ($input as $placeholder=>$value) { 35 | if( strstr($this->errorMessages[$error], $placeholder) ) { 36 | $this->errorMessages[$error] = str_replace('{' .$placeholder . '}', $value, $this->errorMessages[$error]); 37 | } 38 | } 39 | } 40 | return "[ERROR#".$error."] Fatal error: ".$this->errorMessages[$error]."."; 41 | } 42 | 43 | /** 44 | * Выполнить блоковую стркутуру на JSON-файлах. 45 | * @param String $command 46 | * 47 | * @return bool 48 | */ 49 | public function executeBlockSystem(String $command) { 50 | $command = mb_strtolower($command); 51 | $this->__command = $command; 52 | $action = $this->objectToArray($this->read('actions.json')); 53 | 54 | 55 | foreach ($action as &$value) { 56 | if( array_key_exists('question', $value) || array_key_exists('prepare', $value) ) { 57 | if( array_key_exists('send', $value) ) { 58 | $foundPrepare = $this->prepare($value['prepare'], $command); 59 | $foundCommand = false; 60 | $prepareCommand = false; 61 | 62 | 63 | if( array_key_exists('prepare', $value) 64 | && !empty($value['prepare']) 65 | && $foundPrepare ) { 66 | $prepareCommand = true; 67 | } 68 | 69 | if( is_array($value['question']) ) { 70 | foreach ($value['question'] as $question) { 71 | if( $question == $command ) { 72 | $foundCommand = true; 73 | } 74 | } 75 | } else { 76 | if( $value['question'] == $command ) { 77 | $foundCommand = true; 78 | } 79 | } 80 | if ( $foundCommand || 81 | ( 82 | array_key_exists('prepare', $value) 83 | && !empty($value['prepare']) 84 | && $foundPrepare 85 | ) 86 | ) { 87 | if( array_key_exists('message', $value['send']) ) { 88 | if( is_array($value['send']['message']) ) { 89 | if( !array_key_exists(0, $value['send']['message']) ) { 90 | if( array_key_exists('question', $value['send']['message']) && $foundCommand) { 91 | if( is_array($value['send']['message']['question']) ) { 92 | $rand = $this->optionsAnswers($value['send']['message']['question'], 1); 93 | 94 | $tts = ( is_array($value['send']['tts']['question']) ) ? $value['send']['tts']['question'][$rand] : $value['send']['tts']['question']; 95 | 96 | $this->sendMessage($value['send']['message']['question'][$rand], $tts); 97 | } else { 98 | $this->sendMessage($value['send']['message']['question'], $value['send']['tts']['question']); 99 | } 100 | } 101 | if( array_key_exists('prepare', $value['send']['message']) && $prepareCommand) { 102 | if( is_array($value['send']['message']['prepare']) ) { 103 | $rand = $this->optionsAnswers( $value['send']['message']['prepare'], 1 ); 104 | 105 | $tts = ( is_array($value['send']['tts']['prepare']) ) ? $value['send']['tts']['prepare'][$rand] : $value['send']['tts']['prepare']; 106 | 107 | $this->sendMessage( 108 | $this->printVars( $value['send']['message']['prepare'][ $rand ] ), 109 | $this->printVars( $tts ) 110 | ); 111 | } else { 112 | $this->sendMessage( 113 | $this->printVars( $value['send']['message']['prepare']), 114 | $this->printVars( $value['send']['tts']['prepare']) 115 | ); 116 | } 117 | } 118 | } else { 119 | $rand = $this->optionsAnswers($value['send']['message'], 1); 120 | $this->sendMessage($value['send']['message'][$rand], $value['send']['tts'][$rand]); 121 | } 122 | } else { 123 | $this->sendMessage($value['send']['message'], $value['send']['tts']); 124 | } 125 | } 126 | if( array_key_exists('buttons', $value['send']) ) { 127 | if( array_key_exists('question', $value['send']['buttons']) || array_key_exists('prepare', $value['send']['buttons']) ) { 128 | if( $foundCommand ) { 129 | if( is_array($value['send']['buttons']['question'][0]) ) { 130 | foreach ($value['send']['buttons']['question'] as $argument => $val) { 131 | if( array_key_exists('varsToPayload', $value['send']) && $value['send']['varsToPayload'] == true ) { 132 | foreach ($val['payload'] as $nPayload=>$vPayload) { 133 | $val['payload'][$nPayload]['vars'] = 134 | array_merge($val['payload'][$nPayload]['vars'], $this->getVar($value)); 135 | } 136 | } 137 | $this->addButton($val['title'], 138 | $val['hide'], 139 | $val['payload'], 140 | $val['url']); 141 | } 142 | } else { 143 | $buArrayQuestion = $value['send']['buttons']['question']; 144 | foreach ($buArrayQuestion['payload'] as $nPayload=>$vPayload) { 145 | $buArrayQuestion['payload'][$nPayload]['vars'] = 146 | array_merge($buArrayQuestion['payload'][$nPayload]['vars'], $this->getVar($value)); 147 | } 148 | $this->addButton( 149 | $buArrayQuestion['title'], 150 | $buArrayQuestion['hide'], 151 | $buArrayQuestion['payload'], 152 | $buArrayQuestion['url'] 153 | ); 154 | } 155 | } elseif( $prepareCommand ) { 156 | if( is_array($value['send']['buttons']['prepare'][0]) ) { 157 | foreach ($value['send']['buttons']['prepare'] as $argument => $val) { 158 | foreach ($val['payload'] as $nPayload=>$vPayload) { 159 | $val['payload'][$nPayload]['vars'] = 160 | array_merge($val['payload'][$nPayload]['vars'], $this->getVar($value)); 161 | } 162 | $this->addButton($val['title'], 163 | $val['hide'], 164 | $val['payload'], 165 | $val['url']); 166 | 167 | } 168 | } else { 169 | $buArrayPrepare = $value['send']['buttons']['prepare']; 170 | 171 | foreach ($buArrayPrepare['payload'] as $nPayload=>$vPayload) { 172 | $buArrayPrepare['payload'][$nPayload]['vars'] = array_merge($buArrayPrepare['payload'][$nPayload]['vars'], $this->getVar($value)); 173 | } 174 | $this->addButton( 175 | $buArrayPrepare['title'], 176 | $buArrayPrepare['hide'], 177 | $buArrayPrepare['payload'], 178 | $buArrayPrepare['url'] 179 | ); 180 | } 181 | } else { 182 | die($this->errorMessage(3)); 183 | } 184 | } else { 185 | if( is_array($value['send']['buttons'][0]) ) { 186 | foreach ($value['send']['buttons'] as $kb=>$val) { 187 | foreach ($val['payload'] as $nPayload=>$vPayload) { 188 | $val['payload'][$nPayload]['vars'] = 189 | array_merge($val['payload'][$nPayload]['vars'], $this->getVar($value)); 190 | } 191 | $this->addButton( 192 | $val['title'], 193 | $val['hide'], 194 | $val['payload'], 195 | $val['url'] 196 | ); 197 | } 198 | } else { 199 | foreach ($value['send']['buttons']['payload'] as $nPayload=>$vPayload) { 200 | $value['send']['buttons']['payload'][$nPayload]['vars'] = 201 | array_merge($value['send']['buttons']['payload'][$nPayload]['vars'] , $this->getVar($value)); 202 | } 203 | $this->addButton( 204 | $value['send']['buttons']['title'], 205 | $value['send']['buttons']['hide'], 206 | $value['send']['buttons']['payload'], 207 | $value['send']['buttons']['url'] 208 | ); 209 | } 210 | } 211 | } 212 | } else { 213 | return $this->sendMessage( 214 | $this->anyMessage 215 | ); 216 | } 217 | return true; 218 | } else { 219 | die($this->errorMessage(2)); 220 | } 221 | } else { 222 | die($this->errorMessage(1)); 223 | } 224 | } 225 | 226 | return false; 227 | } 228 | 229 | /** 230 | * Получить переменные, чтобы отправить их в Callback. 231 | * @param array $value 232 | * 233 | * @return array 234 | */ 235 | public function getVar(Array $value) { 236 | $params = []; $s = []; 237 | 238 | if( !is_array($value['prepare']) ) { 239 | $words = explode( " ", $value['prepare'] ); 240 | foreach ( $words as $key => $text ) { 241 | if ( strstr($text, '{') && strstr($text, '}') ) { 242 | $var = substr( strstr($text, '{'), 1, strpos($text, '}') - 1 ); 243 | if ( strstr($value['prepare'], "{" . $var . "}" ) ) { 244 | $s[] = $var; 245 | } 246 | } 247 | } 248 | } else { 249 | foreach ($value['prepare'] as $prepare) { 250 | $words = explode( " ", $prepare ); 251 | foreach ( $words as $key => $text ) { 252 | if ( strstr($text, '{') && strstr($text, '}') ) { 253 | $var = substr( strstr($text, '{'), 1, strpos($text, '}') - 1 ); 254 | if ( strstr($prepare, "{" . $var . "}" ) 255 | && $this->__command == str_replace("{".$var."}", $this->vars[$var], $prepare)) { 256 | $s[] = $var; 257 | } 258 | } 259 | } 260 | } 261 | } 262 | $params[$s[0]] = $this->vars[$s[0]]; 263 | 264 | return $params; 265 | } 266 | 267 | public function executePayload(Array $callback) { 268 | $payload = $this->objectToArray( $this->read( 'payload.json' ) ); 269 | $cPayload = count($payload); 270 | $i=0; 271 | foreach ($callback as $key=>$value) { 272 | $message = ""; $tts = ""; $button = []; 273 | foreach ( $payload as $function => $execute ) { 274 | if ( in_array($function, $value) ) { 275 | if( array_key_exists('sendMessage', $execute) ) { 276 | foreach ($execute as &$func) { 277 | $rand = 0; 278 | foreach ($value['vars'] as $param=>$val) { 279 | 280 | if( is_array($func['message']) ) { 281 | $rand = $this->optionsAnswers($func['message'], 1); 282 | $func['message'] = $func['message'][$rand]; 283 | } 284 | 285 | $words = explode(" ", $func['message']); 286 | foreach ($words as $key => $text) { 287 | if (strstr($text, '$') && strstr($text, '$')) { 288 | $var = substr(strstr($text, '$'), 1,strpos($text, '$') - 1); 289 | 290 | if( strstr($text, '^') ) { 291 | $val = $this->spellingCheck($val); 292 | } 293 | $var = str_replace('^', '', $var); 294 | $func['message'] = str_replace('^', '', $func['message']); 295 | 296 | if( strstr($text, "|") ) { 297 | if( explode('|', $var)[0] == $param || explode('|', $var)[1] == $param ) { 298 | $message = $func['message']; 299 | $message = str_replace("$".$var."$", $val, $message); 300 | } 301 | } else { 302 | if( $var == $param ) { 303 | $message = $func['message']; 304 | $message = str_replace("$".$var."$", $val, $message); 305 | } 306 | } 307 | } 308 | } 309 | if( $message == "" ) { 310 | $message = $func['message']; 311 | } 312 | 313 | if( is_array($func['tts']) ) { 314 | $func['tts'] = $func['tts'][$rand]; 315 | } 316 | $wordsTts = explode(" ", $func['tts']); 317 | foreach ($wordsTts as $key => $text) { 318 | if (strstr($text, '$') && strstr($text, '$')) { 319 | $var = substr(strstr($text, '$'), 1,strpos($text, '$') - 1); 320 | if( strstr($text, "|") ) { 321 | if( explode('|', $var)[0] == $param || explode('|', $var)[1] == $param ) { 322 | $tts = $func['tts']; 323 | $tts = str_replace("$".$var."$", $val, $tts); 324 | } 325 | } else { 326 | if( $var == $param ) { 327 | $tts = $func['tts']; 328 | $tts = str_replace("$".$var."$", $val, $tts); 329 | } 330 | } 331 | } 332 | } 333 | if( $tts == "" ) { 334 | $tts = $func['tts']; 335 | } 336 | } 337 | } 338 | } 339 | if( array_key_exists('sendButtons', $execute) ) { 340 | if( is_array($execute['sendButtons'][0]) ) { 341 | foreach ($execute['sendButtons'] as $kb=>$v) { 342 | foreach ($execute['sendButtons'][$kb]['payload'] as $nPayload => $vPayload) { 343 | $execute['sendButtons'][$kb]['payload'][$nPayload]['vars'] = $value['vars']; 344 | } 345 | } 346 | foreach ($execute['sendButtons'] as $kb=>$val) { 347 | $button = $val; 348 | } 349 | } else { 350 | foreach ($execute['sendButtons']['payload'] as $nPayload => $vPayload) { 351 | $execute['sendButtons']['payload'][$nPayload]['vars'] = $value['vars']; 352 | } 353 | $button = $execute['sendButtons']; 354 | } 355 | } 356 | $this->sendPayload($message, $tts, $button); 357 | return true; 358 | } else { 359 | if( $i++ < $cPayload ) { 360 | continue; 361 | } 362 | die( $this->errorMessage(4, ['function'=>$function])); 363 | } 364 | } 365 | } 366 | return false; 367 | } 368 | } -------------------------------------------------------------------------------- /test.php: -------------------------------------------------------------------------------- 1 | "; 8 | print_r($main->uploadImage("images/1.jpg")); 9 | --------------------------------------------------------------------------------