BotsManager.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. <?php
  2. namespace Telegram\Bot;
  3. use Illuminate\Contracts\Container\Container;
  4. use Illuminate\Support\Arr;
  5. use InvalidArgumentException;
  6. use Telegram\Bot\Exceptions\TelegramSDKException;
  7. /**
  8. * Class BotsManager.
  9. *
  10. * @mixin \Telegram\Bot\Api
  11. */
  12. class BotsManager
  13. {
  14. /** @var array The config instance. */
  15. protected $config;
  16. /** @var Container The container instance. */
  17. protected $container;
  18. /** @var array<string, Api> The active bot instances. */
  19. protected $bots = [];
  20. /**
  21. * TelegramManager constructor.
  22. *
  23. * @param array $config
  24. */
  25. public function __construct(array $config)
  26. {
  27. $this->config = $config;
  28. }
  29. /**
  30. * Set the IoC Container.
  31. *
  32. * @param Container $container Container instance
  33. *
  34. * @return BotsManager
  35. */
  36. public function setContainer(Container $container): self
  37. {
  38. $this->container = $container;
  39. return $this;
  40. }
  41. /**
  42. * Get the configuration for a bot.
  43. *
  44. * @param string|null $name
  45. *
  46. * @throws InvalidArgumentException
  47. *
  48. * @return array
  49. */
  50. public function getBotConfig($name = null): array
  51. {
  52. $name = $name ?? $this->getDefaultBotName();
  53. $bots = collect($this->getConfig('bots'));
  54. if (! $config = $bots->get($name, null)) {
  55. throw new InvalidArgumentException("Bot [$name] not configured.");
  56. }
  57. $config['bot'] = $name;
  58. return $config;
  59. }
  60. /**
  61. * Get a bot instance.
  62. *
  63. * @param string|null $name
  64. *
  65. * @throws TelegramSDKException
  66. * @return Api
  67. */
  68. public function bot($name = null): Api
  69. {
  70. $name = $name ?? $this->getDefaultBotName();
  71. if (! isset($this->bots[$name])) {
  72. $this->bots[$name] = $this->makeBot($name);
  73. }
  74. return $this->bots[$name];
  75. }
  76. /**
  77. * Reconnect to the given bot.
  78. *
  79. * @param string|null $name
  80. *
  81. * @throws TelegramSDKException
  82. * @return Api
  83. */
  84. public function reconnect($name = null): Api
  85. {
  86. $name = $name ?? $this->getDefaultBotName();
  87. $this->disconnect($name);
  88. return $this->bot($name);
  89. }
  90. /**
  91. * Disconnect from the given bot.
  92. *
  93. * @param string|null $name
  94. *
  95. * @return BotsManager
  96. */
  97. public function disconnect($name = null): self
  98. {
  99. $name = $name ?? $this->getDefaultBotName();
  100. unset($this->bots[$name]);
  101. return $this;
  102. }
  103. /**
  104. * Get the specified configuration value for Telegram.
  105. *
  106. * @param string $key
  107. * @param mixed $default
  108. *
  109. * @return mixed
  110. */
  111. public function getConfig($key, $default = null)
  112. {
  113. return data_get($this->config, $key, $default);
  114. }
  115. /**
  116. * Get the default bot name.
  117. *
  118. * @return string|null
  119. */
  120. public function getDefaultBotName()
  121. {
  122. return $this->getConfig('default');
  123. }
  124. /**
  125. * Set the default bot name.
  126. *
  127. * @param string $name
  128. *
  129. * @return BotsManager
  130. */
  131. public function setDefaultBot($name): self
  132. {
  133. Arr::set($this->config, 'default', $name);
  134. return $this;
  135. }
  136. /**
  137. * Return all of the created bots.
  138. *
  139. * @return array<string, Api>
  140. */
  141. public function getBots(): array
  142. {
  143. return $this->bots;
  144. }
  145. /**
  146. * De-duplicate an array.
  147. *
  148. * @param array $array
  149. *
  150. * @return array
  151. */
  152. protected function deduplicateArray(array $array): array
  153. {
  154. return array_values(array_unique($array));
  155. }
  156. /**
  157. * Make the bot instance.
  158. *
  159. * @param string $name
  160. *
  161. * @throws TelegramSDKException
  162. * @return Api
  163. */
  164. protected function makeBot($name): Api
  165. {
  166. $config = $this->getBotConfig($name);
  167. $token = data_get($config, 'token');
  168. $telegram = new Api(
  169. $token,
  170. $this->getConfig('async_requests', false),
  171. $this->getConfig('http_client_handler', null)
  172. );
  173. // Check if DI needs to be enabled for Commands
  174. if ($this->getConfig('resolve_command_dependencies', false) && isset($this->container)) {
  175. $telegram->setContainer($this->container);
  176. }
  177. $commands = data_get($config, 'commands', []);
  178. $commands = $this->parseBotCommands($commands);
  179. // Register Commands
  180. $telegram->addCommands($commands);
  181. return $telegram;
  182. }
  183. /**
  184. * @deprecated Will be removed in SDK v4
  185. * @internal
  186. * Builds the list of commands for the given commands array.
  187. *
  188. * @param list<string|class-string<\Telegram\Bot\Commands\CommandInterface>> $commands A list of command names or FQCNs of CommandInterface instances.
  189. *
  190. * @return array An array of commands which includes global and bot specific commands.
  191. */
  192. public function parseBotCommands(array $commands): array
  193. {
  194. $globalCommands = $this->getConfig('commands', []);
  195. $parsedCommands = $this->parseCommands($commands);
  196. return $this->deduplicateArray(array_merge($globalCommands, $parsedCommands));
  197. }
  198. /**
  199. * Parse an array of commands and build a list.
  200. *
  201. * @param list<string|class-string<\Telegram\Bot\Commands\CommandInterface>> $commands
  202. *
  203. * @return array
  204. */
  205. protected function parseCommands(array $commands): array
  206. {
  207. $commandGroups = $this->getConfig('command_groups');
  208. $sharedCommands = $this->getConfig('shared_commands');
  209. //TODO: This is ripe for refactor / collections.
  210. $results = [];
  211. foreach ($commands as $command) {
  212. // If the command is a group, we'll parse through the group of commands
  213. // and resolve the full class name.
  214. if (isset($commandGroups[$command])) {
  215. $results = array_merge(
  216. $results,
  217. $this->parseCommands($commandGroups[$command])
  218. );
  219. continue;
  220. }
  221. // If this command is actually a shared command, we'll extract the full
  222. // class name out of the command list now.
  223. if (isset($sharedCommands[$command])) {
  224. $command = $sharedCommands[$command];
  225. }
  226. if (! in_array($command, $results)) {
  227. $results[] = $command;
  228. }
  229. }
  230. return $results;
  231. }
  232. /**
  233. * Magically pass methods to the default bot.
  234. *
  235. * @param string $method
  236. * @param array $parameters
  237. *
  238. * @throws TelegramSDKException
  239. * @return mixed
  240. */
  241. public function __call($method, $parameters)
  242. {
  243. return call_user_func_array([$this->bot(), $method], $parameters);
  244. }
  245. }