/**
  * Checks and evaluates condition
  * @param string $condition condition string (ex: "$a >= 17")
  * @param array $variables set of variables to substitute
  * @return bool
  */
 public function isConditionMet($condition, array $variables)
 {
     preg_match('/^\\s*(\\$[a-zA-Z\\_]+)\\s*([\\!\\<\\=\\>\\%]+)\\s*(.+)$/', $condition, $matches);
     if (4 !== count($matches)) {
         throw new \LogicException('Error parsing loop condition');
     }
     $variableValue = (int) Ar::get($variables, $matches[1]);
     $result = (int) $matches[3];
     switch ($matches[2]) {
         case '=':
             return $variableValue == $result;
         case '==':
             return $variableValue == $result;
         case '>':
             return $variableValue > $result;
         case '>=':
             return $variableValue >= $result;
         case '<':
             return $variableValue < $result;
         case '<=':
             return $variableValue <= $result;
         case '<>':
             return $variableValue != $result;
         case '!=':
             return $variableValue != $result;
         case '%':
             return ($variableValue + $result) % $result === 0;
         case '!%':
             return ($variableValue + $result) % $result !== 0;
         default:
             throw new \LogicException('Error parsing comparison operator');
     }
 }
 public function resolve($message)
 {
     preg_match_all('/[DGCU]{1}[0-9A-Z]{8}/', $message, $matches);
     if (!is_array(Ar::get($matches, 0)) || 0 === count($matches[0])) {
         return $message;
     }
     foreach ($matches[0] as $match) {
         $replace = null;
         switch ($match[0]) {
             case 'U':
                 $replace = $this->slackFacade->getUserNameById($match);
                 break;
             case 'C':
                 $replace = $this->slackFacade->getChannelById($match)['name'];
                 if (null !== $replace) {
                     $replace = '#' . $replace;
                 }
                 break;
             case 'G':
                 $replace = $this->slackFacade->getGroupById($match)['name'];
                 break;
             case 'D':
                 $replace = $this->slackFacade->getUserInfoByDmId($match)['name'];
                 if (null !== $replace) {
                     $replace = '@' . $replace;
                 }
                 break;
         }
         if (null !== $replace) {
             $message = str_replace($match, $replace, $message);
         }
     }
     return $message;
 }
Example #3
0
 public function send($type, $message, $placeholders = [])
 {
     if (count($placeholders) > 0) {
         $placeholders = array_merge([$message], $placeholders);
         $message = call_user_func_array('sprintf', $placeholders);
     }
     if (true === $this->shouldResolveNames && self::TYPE_RAW !== $type) {
         $message = $this->resolveNamesInMessage($message);
     }
     Ar::each($this->handlers, function ($handler) use($type, $message) {
         /** @var HandlerInterface $handler */
         $handler->send($type, $message);
     });
 }
Example #4
0
 /**
  * Returns array unnamed section bu its subkey
  * @param string $path
  * @param string $searchCriteria
  * @return array
  */
 public function getSectionFromArray($path, $searchCriteria)
 {
     $data = $this->getEntry($path);
     if (!is_array($data)) {
         return [];
     }
     $searchCriteriaData = explode('=', $searchCriteria);
     $fieldName = Ar::get($searchCriteriaData, 0);
     $fieldValue = Ar::get($searchCriteriaData, 1);
     if (null === $fieldName || null === $fieldValue) {
         throw new \LogicException('Invalid config entry search criteria');
     }
     foreach ($data as $item) {
         if (Ar::get($item, $fieldName) === $fieldValue) {
             return $item;
         }
     }
     return [];
 }
 public function processCommand(array $args, $channel)
 {
     /** @var Container $container */
     $container = Registry::get('container');
     /** @var SlackFacade $slackFacade */
     $slackFacade = $container['slack_facade'];
     $currentUserId = $slackFacade->getMyId();
     $this->postMessage($channel, sprintf('I\'m `@%s` (ID `%s`), started %s', $slackFacade->getMyName(), $currentUserId, (new TimeAgoHelper())->format($container['started'])));
     $channels = Ar::map($slackFacade->getUserChannels($currentUserId), function ($channel) {
         return [Ar::get($channel, 'id') => ['name' => Ar::get($channel, 'name'), 'members' => count(Ar::get($channel, 'members'))]];
     });
     $groups = Ar::map($slackFacade->getUserGroups($currentUserId), function ($group) {
         return [Ar::get($group, 'id') => ['name' => Ar::get($group, 'name'), 'members' => count(Ar::get($group, 'members'))]];
     });
     $channelsOutput = (new Tabler())->setRenderer(new MysqlStyleRenderer())->setHeaders(['name' => 'Channel', 'members' => '# of members'])->setData($channels)->render();
     $groupsOutput = (new Tabler())->setRenderer(new MysqlStyleRenderer())->setHeaders(['name' => 'Group', 'members' => '# of members'])->setData($groups)->render();
     $this->postMessage($channel, sprintf('My channels (%d): ```%s```', count($channels), $channelsOutput));
     $this->postMessage($channel, sprintf('My groups (%d): ```%s```', count($groups), $groupsOutput));
 }
 /**
  * @param RequestHandlerInterface $handler
  * @param RequestDto $dto
  * @return bool
  */
 public function shouldExecute(RequestHandlerInterface $handler, RequestDto $dto)
 {
     $section = $this->config->getSection('custom');
     if (empty($section)) {
         return true;
     }
     $dtoChannel = $dto->getChannel();
     if (null === $dtoChannel) {
         return true;
     }
     $handlerId = $handler->getId();
     $handlerConfig = $this->config->getEntry('custom.' . $handlerId);
     if (empty($handlerConfig)) {
         return false;
     }
     $dtoChannelType = $dtoChannel[0];
     if ('D' === $dtoChannelType) {
         return Ar::get($handlerConfig, 'dm') ?: true;
     }
     if ('C' === $dtoChannelType) {
         $dtoChannelInfo = $this->slackApi->channelsInfo($dtoChannel);
         $dtoChannelName = '#' . Ar::get($dtoChannelInfo, 'channel.name');
     } else {
         $dtoChannelInfo = $this->slackApi->groupsInfo($dtoChannel);
         $dtoChannelName = Ar::get($dtoChannelInfo, 'group.name');
     }
     $defaultBehavior = $this->config->getEntry('custom.' . $handlerId . '.default');
     $handlerChannels = $this->config->getEntry('custom.' . $handlerId . '.channels');
     if (empty($handlerChannels)) {
         return 'allow' === $defaultBehavior ? true : false;
     }
     $handlerChannelConfig = $this->config->getSectionFromArray('custom.' . $handlerId . '.channels', 'name=' . $dtoChannelName);
     if (empty($handlerChannelConfig)) {
         return 'allow' === $defaultBehavior ? true : false;
     }
     $this->params = Ar::get($handlerChannelConfig, 'params') ?: [];
     return true;
 }
 /**
  * @param InputInterface $input
  * @param OutputInterface $output
  * @return int
  */
 protected function execute(InputInterface $input, OutputInterface $output)
 {
     $this->logPath = $input->getOption('log');
     $cronInfoUrl = sprintf('http://%s:%d/info/cron/', $input->getOption('host'), $input->getOption('port'));
     $response = json_decode($this->curlRequest->getCurlResult($cronInfoUrl, [CURLOPT_TIMEOUT_MS => 100000])['body'], true);
     if (!is_array($response)) {
         $this->log('Core connection failed, exiting');
         throw new \RuntimeException('Error connecting to core server');
     }
     foreach ($response as $cronItem) {
         $this->cronExpression->setExpression(Ar::get($cronItem, 'time'));
         if ($this->cronExpression->isDue()) {
             $this->log('Executing: ' . Ar::get($cronItem, 'type'));
             switch (Ar::get($cronItem, 'type')) {
                 case 'playbook':
                     $url = sprintf('http://%s:%d/playbook/run/', $input->getOption('host'), $input->getOption('port'));
                     $playbookFile = Ar::get($cronItem, 'playbook');
                     $playbook = $this->fileLoader->load($playbookFile);
                     $this->curlRequest->getCurlResult($url, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => ['playbook' => urlencode($playbook), 'filename' => $playbookFile], CURLOPT_TIMEOUT_MS => 100000]);
                     $this->log('Executed playbook: ' . $playbookFile);
                     break;
                 case 'command':
                     $url = sprintf('http://%s:%d/command/run/', $input->getOption('host'), $input->getOption('port'));
                     $command = Ar::get($cronItem, 'command');
                     if (null === $command) {
                         break;
                     }
                     $this->curlRequest->getCurlResult($url, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => ['command' => urlencode($command)], CURLOPT_TIMEOUT_MS => 100000]);
                     $this->log('Executed command: ' . $command);
                     break;
                 case 'curl':
                     break;
             }
         }
     }
 }
 protected function checkSlackConnection()
 {
     /** @var Container $container */
     $container = Registry::get('container');
     /** @var SlackApi $slackApi */
     $slackApi = $container['slack_api'];
     $this->testResponse = $slackApi->apiTest();
     return (bool) Ar::get($this->testResponse, 'ok');
 }
 public function get($key)
 {
     return Ar::get(self::$data, $key);
 }
Example #10
0
 public function getUserGroups($userId)
 {
     $groups = Ar::get($this->slackApi->groupsList(), 'groups');
     return Ar::filter($groups, function ($group) use($userId) {
         return in_array($userId, Ar::get($group, 'members') ?: []);
     });
 }
Example #11
0
 /**
  * Fires request to Slack server and returns response
  * @param string $method Slack API method to call
  * @param array $data request data
  * @return array
  * @throws \Exception
  */
 private function processRequest($method, $data = [])
 {
     $methodsToFilter = ['api.test', 'rtm.start', 'chat.postMessage'];
     $method = $this->getApiMethodName($method);
     $url = self::BASE_URL . $method;
     $data['token'] = $this->token;
     if (true !== Ar::get($data, 'in_logger')) {
         Logger::get()->raw("➡️ %s", $url, json_encode($data));
     }
     /** @var ApiCache $cache */
     $cache = Registry::get('container')['api_cache'];
     $cachedResponse = $cache->get($url, $data);
     if (null !== $cachedResponse && !in_array($method, $methodsToFilter)) {
         if (true !== Ar::get($data, 'in_logger')) {
             Logger::get()->raw("⬅️ %s: cache hit", $url);
         }
         return $cachedResponse;
     }
     $result = $this->curlRequest->getCurlResult($url, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $data])['body'];
     if (true !== Ar::get($data, 'in_logger')) {
         Logger::get()->raw("⬅️ %s", $url, $result);
     }
     if (!in_array($method, $methodsToFilter)) {
         $cache->set($url, $data, json_decode($result, true));
     }
     return json_decode($result, true);
 }
Example #12
0
 /**
  * Processes !-command
  * @param RequestDto $dto
  */
 public function processCommand(RequestDto $dto)
 {
     $words = preg_split('/\\s+/is', $dto->getText());
     $command = Ar::get($words, 0);
     if (null === $command || '!' !== substr($command, 0, 1)) {
         return;
     }
     $command = substr($command, 1);
     Logger::get()->info("id: %s, %s is executing command \"%s\" at %s", $dto->getId(), $dto->getUser(), $dto->getText(), $dto->getChannel());
     /** @var BaseCommandHandler $commandHandler */
     foreach ($this->commandHandlers as $commandHandler) {
         $commandName = $commandHandler->getName();
         if (is_array($commandName)) {
             if (!in_array($command, $commandName)) {
                 continue;
             }
         } else {
             if ($commandName !== $command) {
                 continue;
             }
         }
         $allowed = $this->checkAccess($dto, $commandHandler);
         if (!$allowed) {
             $this->slackFacade->multiSendMessage([$dto->getChannel()], sprintf('SYSTEM: access to command !%s denied', $commandHandler->getName()));
             Logger::get()->warning("id: %s, access denied for %s trying to run \"%s\" at %s", $dto->getId(), $dto->getUser(), $dto->getText(), $dto->getChannel());
             return;
         }
         unset($words[0]);
         if ($commandHandler->canProcessCommand($words, $dto->getChannel())) {
             /** @var SlackFacade $slackFacade */
             $slackFacade = Registry::get('container')['slack_facade'];
             $commandHandler->setCallerId($dto->getUser());
             $commandHandler->setCallerName($slackFacade->getUserNameById($dto->getUser()));
             Logger::get()->debug("id: %s, starting %s command handler", $dto->getId(), $commandHandler->getName());
             $commandHandler->processCommand($words, $dto->getChannel());
             Logger::get()->debug("id: %s, finished %s command handler", $dto->getId(), $commandHandler->getName());
         }
     }
 }
Example #13
0
 /**
  * Returns variable value
  * @param string $name
  * @return string|null
  */
 public static function get($name)
 {
     return Ar::get(Registry::get('variables'), $name);
 }
Example #14
0
 /**
  * @param string $field field to get
  * @return mixed
  */
 public function get($field)
 {
     return Ar::get($this->data, $field);
 }
Example #15
0
 /**
  * Returns named param or null
  * @param string $name
  * @return null
  */
 public function get($name)
 {
     return Ar::get($this->args, $name);
 }
 /**
  * @param RequestDto $dto
  * @return null
  */
 public function handler(RequestDto $dto)
 {
     // 4a. Timeout, exiting
     if ($this->coreProcessor->isMessageTimedOut($this->handlerId)) {
         $this->slackFacade->getSlackApi()->chatPostMessage($this->recipientId, 'Sorry, response timed out');
         $this->coreProcessor->removeTimedMessageHandler($this->handlerId);
         return;
     }
     // 4b. Processed. Setting variable.
     if ($this->coreProcessor->isMessageHandled($this->handlerId)) {
         $dto = $this->coreProcessor->getTimedMessageHandleResult($this->handlerId);
         if (null === $dto) {
             return;
         }
         $this->coreProcessor->removeTimedMessageHandler($this->handlerId);
         $response = $dto->get('text');
         Variables::set(Ar::get($this->dtoData, 'variable'), $response);
         // 5. Send "after" message
         $afterMessage = Ar::get($this->dtoData, 'messages.after');
         if (null !== $afterMessage) {
             $this->slackFacade->getSlackApi()->chatPostMessage($this->recipientId, $afterMessage);
         }
         // 6. Processing other actions.
         $afterActions = Ar::get($this->dtoData, 'after');
         if (0 === count($afterActions)) {
             return;
         }
         foreach ($afterActions as $afterAction) {
             $actionDto = $this->createActionDto();
             $this->populateActionDto($actionDto, $afterAction);
             $this->coreProcessor->processAction($actionDto);
         }
     }
 }
Example #17
0
 public function buildLogger(Container $container)
 {
     $logger = new Logger($container['names_resolver']);
     /** @var Config $config */
     $config = $container['config'];
     $loggingConfig = $config->getSection('logging');
     $shouldResolve = Ar::get($loggingConfig, 'resolve') ?: false;
     $logger->setResolveNames($shouldResolve);
     $loggingEntries = Ar::get($loggingConfig, 'handlers') ?: [];
     Ar::each($loggingEntries, function ($loggingEntry) use($logger, $container) {
         $filter = Ar::get($loggingEntry, 'filter') ?: 255;
         $handlerName = Ar::get($loggingEntry, 'handler');
         switch ($handlerName) {
             case 'slack':
                 $channels = Ar::get($loggingEntry, 'channels') ?: [];
                 $handler = (new SlackHandler($container['slack_facade']))->setChannels($channels)->setFilter($filter);
                 break;
             case 'console':
                 $handler = (new ConsoleOutputHandler())->setFilter($filter);
                 break;
             default:
                 return;
         }
         $logger->addHandler($handler);
     });
     $container['logger'] = $logger;
 }
 /**
  * Main execution loop
  * @throws \Exception
  */
 protected function processLoop()
 {
     while (true) {
         try {
             $data = $this->client->receive();
             $parsedData = json_decode($data, true);
             if ('message' === Ar::get($parsedData, 'type') && 'bot_message' !== Ar::get($parsedData, 'subtype')) {
                 echo sprintf("[INFO] Got message: '%s' from %s in %s\n", Ar::get($parsedData, 'text') ?: '<nothing>', Ar::get($parsedData, 'user') ?: 'bot', Ar::get($parsedData, 'channel') ?: 'unknown channel');
                 try {
                     $this->curlRequest->getCurlResult($this->serverUrl, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => ['message' => $data]]);
                 } catch (\Exception $e) {
                 }
             }
         } catch (Exception $e) {
             $result = $this->curlRequest->getCurlResult($this->authUrl);
             $result = json_decode($result['body'], true);
             $this->socketUrl = $result['url'];
             $this->client = $this->createClient();
         }
     }
 }
Example #19
0
File: ArTest.php Project: eznio/ar
 /**
  * @test
  * @dataProvider arrayMapDataProvider
  * @param array $arrayToMap
  * @param callable $mapperCallback
  * @param mixed $sampler
  */
 public function shouldReturnRightArrayMapValues($arrayToMap, $mapperCallback, $sampler)
 {
     $result = Ar::map($arrayToMap, $mapperCallback);
     $this->assertEquals($sampler, $result);
 }
 /**
  * @param $type
  * @param $message
  * @return void
  */
 public function send($type, $message)
 {
     if (!$this->isFiltered($type)) {
         echo sprintf("[%s] %s\n", strtoupper(Ar::get(Logger::TYPE_NAMES, $type)) ?: '?', $message);
     }
 }