api.wolfdispatcher.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856
  1. <?php
  2. /**
  3. * Universal Telegram bot hooks processing extendable class
  4. */
  5. class WolfDispatcher {
  6. /**
  7. * Contains current instance bot token
  8. *
  9. * @var string
  10. */
  11. protected $botToken = '';
  12. /**
  13. * Contains text commands=>actions mappings
  14. *
  15. * @var array
  16. */
  17. protected $commands = array();
  18. /**
  19. * Group chats commands array which overrides normal actions only for group chats
  20. *
  21. * @var array
  22. */
  23. protected $groupChatCommands = array();
  24. /**
  25. * Chats commands array which required user set in adminChatIds struct to be executed.
  26. *
  27. * @var array
  28. */
  29. protected $adminCommands = array();
  30. /**
  31. * Contains text reactions=>actions mappings
  32. *
  33. * @var array
  34. */
  35. protected $textReacts = array();
  36. /**
  37. * Array of chatIds which is denied for any actions performing
  38. *
  39. * @var array
  40. */
  41. protected $ignoredChatIds = array();
  42. /**
  43. * Contains administrator users chatIds as chatId=>index
  44. *
  45. * @var array
  46. */
  47. protected $adminChatIds = array();
  48. /**
  49. * Array of chatIds which is allowed for actions execution. Ignored if empty.
  50. *
  51. * @var array
  52. */
  53. protected $allowedChatIds = array();
  54. /**
  55. * Telegram interraction layer object placeholder
  56. *
  57. * @var object
  58. */
  59. protected $telegram = '';
  60. /**
  61. * Input data storage
  62. *
  63. * @var array
  64. */
  65. protected $receivedData = array();
  66. /**
  67. * Current conversation client chatId
  68. *
  69. * @var int
  70. */
  71. protected $chatId = 0;
  72. /**
  73. * Current conversation latest messageId
  74. *
  75. * @var int
  76. */
  77. protected $messageId = 0;
  78. /**
  79. * Current converstation chat type, like private,group
  80. *
  81. * @var string
  82. */
  83. protected $chatType = '';
  84. /**
  85. * Method name which will be executed on any image receive
  86. *
  87. * @var string
  88. */
  89. protected $photoHandleMethod = '';
  90. /**
  91. * Method name which will be executed if any new chat member appears
  92. *
  93. * @var string
  94. */
  95. protected $chatMemberAppearMethod = '';
  96. /**
  97. * Method name which will be executed if any new chat member left chat
  98. *
  99. * @var string
  100. */
  101. protected $chatMemberLeftMethod = '';
  102. /**
  103. * Dispatcher debugging flag
  104. *
  105. * @var bool
  106. */
  107. protected $debugFlag = false;
  108. /**
  109. * Contains all called actions/methods
  110. *
  111. * @var string
  112. */
  113. protected $calledActions = array();
  114. /**
  115. * Contains current bot instance class name as is
  116. *
  117. * @var string
  118. */
  119. protected $botImplementation = '';
  120. /**
  121. * Web-hook automatic installation flag
  122. *
  123. * @var bool
  124. */
  125. protected $hookAutoSetup = false;
  126. /**
  127. * Contains default debug log path
  128. */
  129. const LOG_PATH = 'exports/';
  130. /**
  131. * Contains path to save web hooks PIDs due autosetup.
  132. */
  133. const HOOK_PID_PATH = 'exports/';
  134. /**
  135. * Creates new dispatcher instance
  136. *
  137. * @param string $token
  138. *
  139. * @return void
  140. */
  141. public function __construct($token) {
  142. if (!empty($token)) {
  143. $this->botToken = $token;
  144. }
  145. // , ,
  146. // |\---/|
  147. // / , , |
  148. // __.-'| / \ /
  149. // __ ___.-' ._O|
  150. // .-' ' : _/
  151. // / , . . |
  152. // : ; : : _/
  153. // | | .' __: /
  154. // | : /'----'| \ |
  155. // \ |\ | | /| |
  156. // '.'| / || \ |
  157. // | /|.' '.l \\_
  158. // || || '-'
  159. // '-''-'
  160. $this->initTelegram();
  161. $this->setBotName();
  162. }
  163. /**
  164. * Sets current bot instance implementation property
  165. *
  166. * @return void
  167. */
  168. protected function setBotName() {
  169. $this->botImplementation = get_class($this);
  170. }
  171. /**
  172. * Instance debugging flag setter. Debug log: exports/botname_debug.log
  173. *
  174. * @param bool $state
  175. *
  176. * @return void
  177. */
  178. public function setDebug($state) {
  179. if ($state) {
  180. $this->debugFlag = true;
  181. }
  182. }
  183. /**
  184. * Inits protected telegram instance
  185. *
  186. * @throws Exception
  187. *
  188. * @return void
  189. */
  190. protected function initTelegram() {
  191. if (!empty($this->botToken)) {
  192. if (class_exists('UbillingTelegram')) {
  193. $this->telegram = new UbillingTelegram($this->botToken);
  194. } else {
  195. if (class_exists('WolfGram')) {
  196. $this->telegram = new WolfGram($this->botToken);
  197. }
  198. }
  199. if (empty($this->telegram)) {
  200. throw new Exception('EX_NO_TELEGRAM_LIB');
  201. }
  202. } else {
  203. throw new Exception('EX_EMPTY_TOKEN');
  204. }
  205. }
  206. /**
  207. * Sets new dispatcher actions dataset
  208. *
  209. * @param array $commands dataset as text input=>method or function name
  210. *
  211. * @return void
  212. */
  213. public function setActions($commands) {
  214. if (!empty($commands)) {
  215. if (is_array($commands)) {
  216. $this->commands = $commands;
  217. }
  218. }
  219. }
  220. /**
  221. * Sets group commands data set
  222. * If not empty data set its overrides all default actions for not private chats
  223. *
  224. * @param array $groupCommands dataset as text input=>method or function name
  225. *
  226. * @return void
  227. */
  228. public function setGroupActions($groupCommands) {
  229. $this->groupChatCommands = $groupCommands;
  230. }
  231. /**
  232. * Sets admin commands data set. This actions requires user to be isAdmin() for execution
  233. *
  234. * @param array $adminCommands dataset as text input=>method or function name
  235. *
  236. * @return void
  237. */
  238. public function setAdminActions($adminCommands) {
  239. $this->adminCommands = $adminCommands;
  240. }
  241. /**
  242. * Sets administrative user chatIDs
  243. *
  244. * @param array $chatIds just array of chatids of administrative users like array('111111','222222')
  245. *
  246. * @return void
  247. */
  248. public function setAdminChatId($chatIds) {
  249. if (!empty($chatIds)) {
  250. $chatIds = array_flip($chatIds);
  251. $this->adminChatIds = $chatIds;
  252. }
  253. }
  254. /**
  255. * Sets new dispatcher text reactions dataset. Basic setActions dataset overrides this.
  256. *
  257. * @param array $commands dataset as text input=>method or function name
  258. *
  259. * @return void
  260. */
  261. public function setTextReactions($commands) {
  262. if (!empty($commands)) {
  263. if (is_array($commands)) {
  264. $this->textReacts = $commands;
  265. }
  266. }
  267. }
  268. /**
  269. * Sets method name which will be executed on any image input
  270. *
  271. * @param string $name existing method name to process received images
  272. *
  273. * @return void
  274. */
  275. public function setPhotoHandler($name) {
  276. if (!empty($name)) {
  277. $this->photoHandleMethod = $name;
  278. }
  279. }
  280. /**
  281. * Sets method names which will be executed if some member appears or left chat
  282. *
  283. * @param string $methodAppear
  284. * @param string $methodLeft
  285. *
  286. * @return void
  287. */
  288. public function setOnChatMemberActions($methodAppear = '', $methodLeft = '') {
  289. if (!empty($methodAppear)) {
  290. $this->chatMemberAppearMethod = $methodAppear;
  291. }
  292. if (!empty($methodLeft)) {
  293. $this->chatMemberLeftMethod = $methodLeft;
  294. }
  295. }
  296. /**
  297. * Sets allowed chat IDs for this instance
  298. *
  299. * @param array $chatIds chatIds which only allowed to interract this bot instance just like array('1234','4321')
  300. *
  301. * @return void
  302. */
  303. public function setAllowedChatIds($chatIds) {
  304. if (!empty($chatIds)) {
  305. if (is_array($chatIds)) {
  306. $this->allowedChatIds = array_flip($chatIds);
  307. }
  308. }
  309. }
  310. /**
  311. * Sets denied chat IDs for this instance
  312. *
  313. * @param array $chatIds chatIds which is denied from interraction with this instance just like array('1234','4321')
  314. *
  315. * @return void
  316. */
  317. public function setIgnoredChatIds($chatIds) {
  318. if (!empty($chatIds)) {
  319. if (is_array($chatIds)) {
  320. $this->ignoredChatIds = array_flip($chatIds);
  321. }
  322. }
  323. }
  324. /**
  325. * Getting current input text action name if it exists
  326. *
  327. * @return string
  328. */
  329. protected function getTextAction() {
  330. $result = '';
  331. //basic commands processing
  332. if (!empty($this->commands)) {
  333. foreach ($this->commands as $eachCommand => $eachAction) {
  334. if (mb_stripos($this->receivedData['text'], $eachCommand, 0, 'UTF-8') !== false) {
  335. $result = $eachAction;
  336. }
  337. }
  338. }
  339. //administrative commands processing
  340. if (!empty($this->adminCommands)) {
  341. if ($this->isAdmin()) {
  342. foreach ($this->adminCommands as $eachCommand => $eachAction) {
  343. if (mb_stripos($this->receivedData['text'], $eachCommand, 0, 'UTF-8') !== false) {
  344. $result = $eachAction;
  345. }
  346. }
  347. }
  348. }
  349. //text reactions if no of main commands detected
  350. if (empty($result)) {
  351. if (!empty($this->textReacts)) {
  352. foreach ($this->textReacts as $eachTextReact => $eachAction) {
  353. if (mb_stripos($this->receivedData['text'], $eachTextReact, 0, 'UTF-8') !== false) {
  354. $result = $eachAction;
  355. }
  356. }
  357. }
  358. }
  359. return($result);
  360. }
  361. /**
  362. * Performs run of some action into current dispatcher instance
  363. *
  364. * @param string $actionName
  365. *
  366. * @return void
  367. */
  368. protected function runAction($actionName) {
  369. if (!empty($actionName)) {
  370. if (method_exists($this, $actionName)) {
  371. //class methods have priority
  372. $this->$actionName();
  373. if ($this->debugFlag) {
  374. $this->calledActions[] = 'METHOD: ' . $actionName;
  375. }
  376. } else {
  377. if (function_exists($actionName)) {
  378. $actionName($this->receivedData);
  379. if ($this->debugFlag) {
  380. $this->calledActions[] = 'FUNC: ' . $actionName;
  381. }
  382. } else {
  383. if ($this->debugFlag) {
  384. //any command/reaction handler found
  385. $chatId = $this->receivedData['chat']['id'];
  386. $message = __('Any existing function on method named') . ' `' . $actionName . '` ' . __('not found by dispatcher');
  387. $this->telegram->directPushMessage($chatId, $message);
  388. if ($this->debugFlag) {
  389. $this->calledActions[] = 'FAILED: ' . $actionName;
  390. }
  391. }
  392. }
  393. }
  394. }
  395. }
  396. /**
  397. * Run some actions on non empty input data received
  398. *
  399. * @return void
  400. */
  401. protected function reactInput() {
  402. $currentInputAction = '';
  403. if (!empty($this->receivedData)) {
  404. if (isset($this->receivedData['from']) AND isset($this->receivedData['chat'])) {
  405. $chatId = $this->receivedData['chat']['id']; //yeah, we waiting for preprocessed data here
  406. $interractionAllowed = true;
  407. //separate allows here
  408. if (!empty($this->allowedChatIds)) {
  409. if (!isset($this->allowedChatIds[$chatId])) {
  410. $interractionAllowed = false;
  411. }
  412. }
  413. //something like ban list
  414. if (isset($this->ignoredChatIds[$chatId])) {
  415. $interractionAllowed = false;
  416. }
  417. if ($interractionAllowed) {
  418. //interraction with this chat id is allowed
  419. if (!empty($this->receivedData['text'])) {
  420. $currentInputAction = $this->getTextAction();
  421. if (!empty($currentInputAction)) {
  422. $this->runAction($currentInputAction);
  423. } else {
  424. //empty actions here. No of existing commands or reactions found here.
  425. $this->handleEmptyAction();
  426. }
  427. } else {
  428. //empty text actions here
  429. $this->handleEmptyText();
  430. }
  431. //this method will be executed on image receive if set
  432. if (!empty($this->photoHandleMethod)) {
  433. if ($this->isPhotoReceived()) {
  434. $this->runAction($this->photoHandleMethod);
  435. }
  436. }
  437. //following methods will be executed while new member appears in chat or lefts the chat
  438. if (!empty($this->chatMemberAppearMethod)) {
  439. if ($this->isNewChatMemberAppear()) {
  440. $this->runAction($this->chatMemberAppearMethod);
  441. }
  442. }
  443. if (!empty($this->chatMemberLeftMethod)) {
  444. if ($this->isChatMemberLeft()) {
  445. $this->runAction($this->chatMemberLeftMethod);
  446. }
  447. }
  448. //this will be executed if some image received anyway
  449. if ($this->isPhotoReceived()) {
  450. $this->handlePhotoReceived();
  451. }
  452. }
  453. }
  454. //this shall be executed on any non empty data recieve
  455. $this->handleAnyWay();
  456. }
  457. }
  458. /**
  459. * Dummy method which will be executed on receive empty text actions on listener
  460. *
  461. * @return void
  462. */
  463. protected function handleEmptyAction() {
  464. //will be executed on messages with no detected action for message
  465. }
  466. /**
  467. * Dummy method which will be executed on receive empty text actions on listener
  468. *
  469. * @return void
  470. */
  471. protected function handleEmptyText() {
  472. //will be executed on messages with empty text field
  473. }
  474. /**
  475. * Dummy method which will be executed on receive any non empty data on listener
  476. *
  477. * @return void
  478. */
  479. protected function handleAnyWay() {
  480. //will be executed on eny non empty received data
  481. }
  482. /**
  483. * Dummy method which will be executed on receive any image file
  484. *
  485. * @return void
  486. */
  487. protected function handlePhotoReceived() {
  488. //will be executed if any image received
  489. }
  490. /**
  491. * Writes debug data to separate per-class log if debugging flag enabled.
  492. *
  493. * @global int $starttime
  494. * @global int $query_counter
  495. *
  496. * @return void
  497. */
  498. protected function writeDebugLog() {
  499. global $starttime, $query_counter;
  500. if ($this->debugFlag) {
  501. $nowmtime = explode(' ', microtime());
  502. $wtotaltime = $nowmtime[0] + $nowmtime[1] - $starttime;
  503. $logData = $this->botImplementation . ': ' . curdatetime() . PHP_EOL;
  504. $logData .= print_r($this->receivedData, true) . PHP_EOL;
  505. $logData .= 'GT: ' . round($wtotaltime, 4) . ' QC: ' . $query_counter . PHP_EOL;
  506. if (!empty($this->calledActions)) {
  507. $logData .= PHP_EOL . 'Called actions: ' . print_r($this->calledActions, true) . PHP_EOL;
  508. } else {
  509. $logData .= PHP_EOL . 'Called actions: NONE' . PHP_EOL;
  510. }
  511. $logData .= '==================' . PHP_EOL;
  512. $logFileName = strtolower($this->botImplementation) . '_debug.log';
  513. file_put_contents(self::LOG_PATH . $logFileName, $logData, FILE_APPEND);
  514. }
  515. }
  516. /**
  517. * Listens for some events
  518. *
  519. * @return array
  520. */
  521. public function listen() {
  522. //may be automatic setup required?
  523. $this->installWebHook();
  524. //is something here?
  525. $this->receivedData = $this->telegram->getHookData();
  526. if (!empty($this->receivedData)) {
  527. @$this->chatId = $this->receivedData['chat']['id'];
  528. @$this->messageId = $this->receivedData['message_id'];
  529. @$this->chatType = $this->receivedData['chat']['type'];
  530. //wow, some separate group commands here. They overrides all another actions.
  531. if (!empty($this->groupChatCommands)) {
  532. if ($this->chatType != 'private') {
  533. //override actions with another group set
  534. $this->setActions($this->groupChatCommands);
  535. }
  536. }
  537. $this->reactInput();
  538. }
  539. $this->writeDebugLog();
  540. return($this->receivedData);
  541. }
  542. /**
  543. * Checks is any image received?
  544. *
  545. * @return bool
  546. */
  547. protected function isPhotoReceived() {
  548. $result = false;
  549. if ($this->receivedData['photo'] OR $this->receivedData['document']) {
  550. $imageMimeTypes = array('image/png', 'image/jpeg');
  551. if ($this->receivedData['photo']) {
  552. $result = true;
  553. } else {
  554. if ($this->receivedData['document']) {
  555. $imageMimeTypes = array_flip($imageMimeTypes);
  556. if (isset($imageMimeTypes[$this->receivedData['document']['mime_type']])) {
  557. $result = true;
  558. }
  559. }
  560. }
  561. }
  562. return($result);
  563. }
  564. /**
  565. * Checks is new chat member appeared in chat? Returns his data on this event.
  566. * Data fields:
  567. * id, is_bot, first_name, username, language_code, is_premium - normal users
  568. * id, is_bot, first_name, username - bots
  569. *
  570. * @return array/bool
  571. */
  572. protected function isNewChatMemberAppear() {
  573. $result = false;
  574. if ($this->receivedData['new_chat_member']) {
  575. $result = $this->receivedData['new_chat_member'];
  576. }
  577. return($result);
  578. }
  579. /**
  580. * Checks is any chat member lefts chat? Returns his chatId on this event.
  581. * Data fields:
  582. * id, is_bot, first_name, username, language_code, is_premium - normal users
  583. * id, is_bot, first_name, username - bots
  584. *
  585. * @return array/bool
  586. */
  587. protected function isChatMemberLeft() {
  588. $result = false;
  589. if ($this->receivedData['left_chat_member']) {
  590. $result = $this->receivedData['left_chat_member'];
  591. }
  592. return($result);
  593. }
  594. /**
  595. * Checks is current user chatId listed as administrator?
  596. *
  597. * @return bool
  598. */
  599. protected function isAdmin() {
  600. $result = false;
  601. if (!empty($this->adminChatIds)) {
  602. //direct message in private chat?
  603. if (isset($this->adminChatIds[$this->chatId])) {
  604. $result = true;
  605. } else {
  606. //may be group chat message from admin user?
  607. if (isset($this->adminChatIds[$this->receivedData['from']['id']])) {
  608. $result = true;
  609. }
  610. }
  611. }
  612. return($result);
  613. }
  614. /**
  615. * Returns current received message as receivedData struct
  616. *
  617. * @return array
  618. */
  619. protected function message() {
  620. return($this->receivedData);
  621. }
  622. /**
  623. * Returns received image file content
  624. *
  625. * @return mixed
  626. */
  627. protected function getPhoto() {
  628. $result = '';
  629. $filePath = '';
  630. $fileId = '';
  631. $imageMimeTypes = array('image/png', 'image/jpeg');
  632. //normal compressed image
  633. if ($this->receivedData['photo']) {
  634. $maxSizeFile = end($this->receivedData['photo']);
  635. $fileId = $maxSizeFile['file_id'];
  636. } else {
  637. //image received as-is without compression
  638. $imageMimeTypes = array_flip($imageMimeTypes);
  639. if ($this->receivedData['document']) {
  640. if (isset($imageMimeTypes[$this->receivedData['document']['mime_type']])) {
  641. $fileId = $this->receivedData['document']['file_id'];
  642. }
  643. }
  644. }
  645. //downloading remote file
  646. if ($fileId) {
  647. $filePath = $this->telegram->getFilePath($fileId);
  648. if ($filePath) {
  649. $result = $this->telegram->downloadFile($filePath);
  650. }
  651. }
  652. return($result);
  653. }
  654. /**
  655. * Saves received photo to the specified path on filesystem. Returns filepath on success.
  656. *
  657. * @param string $savePath
  658. *
  659. * @return string/void
  660. */
  661. protected function savePhoto($savePath) {
  662. $result = '';
  663. if (!empty($savePath)) {
  664. if ($this->isPhotoReceived()) {
  665. $receivedPhoto = $this->getPhoto();
  666. if ($receivedPhoto) {
  667. file_put_contents($savePath, $receivedPhoto);
  668. if (file_exists($savePath)) {
  669. $result = $savePath;
  670. }
  671. }
  672. }
  673. }
  674. return($result);
  675. }
  676. /**
  677. * Sends fast reply to current chat member
  678. *
  679. * @param string $message
  680. * @param array $keyboard
  681. *
  682. * @return string/bool
  683. */
  684. protected function reply($message = '', $keyboard = array()) {
  685. $result = '';
  686. if (!empty($message)) {
  687. $replyResult = $this->telegram->directPushMessage($this->chatId, $message, $keyboard);
  688. if ($replyResult) {
  689. $result = json_decode($replyResult, true);
  690. }
  691. }
  692. return($result);
  693. }
  694. /**
  695. * Sends fast reply to current chat member for latest message or some specified messageId
  696. *
  697. * @param string $message
  698. * @param array $keyboard
  699. * @param int $replyToMsg
  700. *
  701. * @return string/bool
  702. */
  703. protected function replyTo($message = '', $keyboard = array(), $replyToMsg = '') {
  704. $result = '';
  705. if (!empty($message)) {
  706. if (empty($replyToMsg)) {
  707. $replyToMsg = $this->messageId;
  708. }
  709. $replyResult = $this->telegram->directPushMessage($this->chatId, $message, $keyboard, false, $replyToMsg);
  710. if ($replyResult) {
  711. $result = json_decode($replyResult, true);
  712. }
  713. }
  714. return($result);
  715. }
  716. /**
  717. * Sends some keyboard to current chat
  718. *
  719. * @param array $buttons
  720. * @param string $text
  721. *
  722. * @return void
  723. */
  724. protected function castKeyboard($buttons, $text = '⌨️') {
  725. if (!empty($buttons)) {
  726. $keyboard = $this->telegram->makeKeyboard($buttons);
  727. $this->reply($text, $keyboard);
  728. }
  729. }
  730. /**
  731. * Enables or disables web-hook automatic installation
  732. *
  733. * @param bool $enabled is web-hook autosetup enabled?
  734. *
  735. * @return void
  736. */
  737. public function hookAutosetup($enabled = true) {
  738. $this->hookAutoSetup = $enabled;
  739. }
  740. /**
  741. * Automatically registers new web-hook URL for bot if isnt registered yet.
  742. *
  743. * @return void
  744. */
  745. protected function installWebHook() {
  746. if ($this->hookAutoSetup) {
  747. $listenerUrl = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  748. $tokenHash = md5($this->botToken . $listenerUrl);
  749. $hookPidName = self::HOOK_PID_PATH . $this->botImplementation . $tokenHash . '.hook';
  750. //need to be installed?
  751. if (!file_exists($hookPidName)) {
  752. $hookInfo = json_decode($this->telegram->getWebHookInfo(), true);
  753. if ($hookInfo['result']['url'] != $listenerUrl) {
  754. //need to be installed new URL
  755. $this->telegram->setWebHook($listenerUrl, 100);
  756. if (function_exists('show_success')) {
  757. show_success($this->botImplementation . ' web-hook URL: ' . $hookInfo['result']['url']);
  758. }
  759. } else {
  760. //already set, but no PID
  761. if (function_exists('show_warning')) {
  762. show_warning($this->botImplementation . ' web-hook URL: ' . $hookInfo['result']['url']);
  763. }
  764. }
  765. //write hook pid
  766. file_put_contents($hookPidName, $listenerUrl);
  767. //some logging
  768. if ($this->debugFlag) {
  769. $logFileName = strtolower($this->botImplementation) . '_debug.log';
  770. $logData = $this->botImplementation . ': ' . curdatetime() . PHP_EOL;
  771. $logData .= 'INSTALLED WEB HOOK: ' . $listenerUrl . PHP_EOL;
  772. $logData .= 'HOOK PID: ' . $hookPidName . PHP_EOL;
  773. file_put_contents(self::LOG_PATH . $logFileName, $logData, FILE_APPEND);
  774. }
  775. } else {
  776. //ok, hook is already installed
  777. $currentHookUrl = file_get_contents($hookPidName);
  778. if (function_exists('show_info')) {
  779. show_info($this->botImplementation . ' web-hook URL: ' . $currentHookUrl);
  780. }
  781. }
  782. }
  783. }
  784. }