Beispiel #1
0
 private function disable(CommandMessage $command) : Promise
 {
     return resolve(function () use($command) {
         if (!(yield $this->adminStorage->isAdmin($command->getRoom(), $command->getUserId()))) {
             return $this->chatClient->postReply($command, "I'm sorry Dave, I'm afraid I can't do that");
         }
         if (null === ($plugin = $command->getParameter(1))) {
             return $this->chatClient->postReply($command, "No plugin name supplied");
         }
         if (!$this->pluginManager->isPluginRegistered($plugin)) {
             return $this->chatClient->postReply($command, "Invalid plugin name");
         }
         if (!$this->pluginManager->isPluginEnabledForRoom($plugin, $command->getRoom())) {
             return $this->chatClient->postReply($command, "Plugin already disabled in this room");
         }
         (yield $this->pluginManager->disablePluginForRoom($plugin, $command->getRoom()));
         return $this->chatClient->postMessage($command->getRoom(), "Plugin '{$plugin}' is now disabled in this room");
     });
 }
 public function handleCommand(Command $command) : Promise
 {
     return resolve(function () use($command) {
         $commandName = $command->getCommandName();
         if (!isset($this->commands[$commandName])) {
             return;
         }
         $eventId = $command->getEvent()->getId();
         $userId = $command->getUserId();
         try {
             $userIsBanned = (yield $this->banStorage->isBanned($command->getRoom(), $userId));
             if ($userIsBanned) {
                 $this->logger->log(Level::DEBUG, "User #{$userId} is banned, ignoring event #{$eventId} for built in commands");
                 return;
             }
             $this->logger->log(Level::DEBUG, "Passing event #{$eventId} to built in command handler " . get_class($this->commands[$commandName]));
             (yield $this->commands[$commandName]->handleCommand($command));
         } catch (\Throwable $e) {
             $this->logger->log(Level::ERROR, "Something went wrong while handling #{$eventId} for built-in commands: {$e}");
         }
     });
 }
Beispiel #3
0
 public function unpin(Command $command)
 {
     $owners = (yield $this->chatClient->getRoomOwners($command->getRoom()));
     if (!isset($owners[$command->getUserId()])) {
         return $this->chatClient->postReply($command, "I'm sorry Dave, I'm afraid I can't do that");
     }
     if (!$command->hasParameters(1)) {
         return $this->chatClient->postReply($command, "You must supply a valid message ID to unpin");
     }
     if (!preg_match('#(?:messages?/)?([0-9]+)#', $command->getParameter(0), $match)) {
         return $this->chatClient->postReply($command, "You must supply a valid message ID to unpin");
     }
     $key = $match[1];
     $id = (int) $key;
     if (!(yield $this->keyValueStore->exists($key, $command->getRoom()))) {
         return $this->chatClient->postReply($command, "You must supply a valid message ID to unpin");
     }
     (yield $this->keyValueStore->unset($key, $command->getRoom()));
     if (in_array($id, (yield $this->chatClient->getPinnedMessages($command->getRoom())))) {
         (yield $this->chatClient->pinOrUnpinMessage($id, $command->getRoom()));
     }
     return $this->chatClient->postMessage($command->getRoom(), "I will no longer repin message #{$id}");
 }
Beispiel #4
0
 private function execute(CommandMessage $command) : \Generator
 {
     if (!(yield $command->getRoom()->isApproved())) {
         return;
     }
     if (!(yield $this->adminStorage->isAdmin($command->getRoom(), $command->getUserId()))) {
         return $this->chatClient->postReply($command, "I'm sorry Dave, I'm afraid I can't do that");
     }
     if ($command->getCommandName() === "ban" && $command->getParameter(0) === 'list') {
         yield from $this->list($command);
     } else {
         if ($command->getCommandName() === "ban") {
             if (!$command->hasParameters(2)) {
                 return $this->chatClient->postReply($command, "Ban length must be specified");
             }
             yield from $this->add($command, (int) $command->getParameter(0), $command->getParameter(1));
         } else {
             if ($command->getCommandName() === "unban") {
                 yield from $this->remove($command, (int) $command->getParameter(0));
             }
         }
     }
 }
Beispiel #5
0
 public function tweet(Command $command)
 {
     if (!$this->isMessageValid($command->getParameter(0))) {
         return new Success();
     }
     if (!(yield $this->admin->isAdmin($command->getRoom(), $command->getUserId()))) {
         return $this->chatClient->postReply($command, "I'm sorry Dave, I'm afraid I can't do that");
     }
     $tweetText = (yield from $this->getMessage($command, $command->getParameters()[0]));
     if (mb_strlen($tweetText, "UTF-8") > 140) {
         return $this->chatClient->postReply($command, "Boo! The message exceeds the 140 character limit. :-(");
     }
     $keys = ['oauth.consumer_key', 'oauth.access_token', 'oauth.consumer_secret', 'oauth.access_token_secret'];
     $config = [];
     foreach ($keys as $key) {
         if (!(yield $this->storage->exists($key, $command->getRoom()))) {
             return $this->chatClient->postReply($command, "I'm not currently configured for tweeting :-(");
         }
         $config[$key] = (yield $this->storage->get($key, $command->getRoom()));
     }
     $oauthParameters = ["oauth_consumer_key" => $config['oauth.consumer_key'], "oauth_token" => $config['oauth.access_token'], "oauth_nonce" => $this->getNonce(), "oauth_timestamp" => (new \DateTimeImmutable())->format("U"), "oauth_signature_method" => "HMAC-SHA1", "oauth_version" => "1.0", "status" => $tweetText];
     $oauthParameters = array_map("rawurlencode", $oauthParameters);
     asort($oauthParameters);
     ksort($oauthParameters);
     $queryString = urldecode(http_build_query($oauthParameters, '', '&'));
     $baseString = "POST&" . rawurlencode(self::BASE_URI . "/statuses/update.json") . "&" . rawurlencode($queryString);
     $key = $config['oauth.consumer_secret'] . "&" . $config['oauth.access_token_secret'];
     $signature = rawurlencode(base64_encode(hash_hmac('sha1', $baseString, $key, true)));
     $oauthParameters["oauth_signature"] = $signature;
     $oauthParameters = array_map(function ($value) {
         return '"' . $value . '"';
     }, $oauthParameters);
     unset($oauthParameters["status"]);
     asort($oauthParameters);
     ksort($oauthParameters);
     $authorizationHeader = $auth = "OAuth " . urldecode(http_build_query($oauthParameters, '', ', '));
     $request = (new HttpRequest())->setUri(self::BASE_URI . "/statuses/update.json")->setMethod('POST')->setProtocol('1.1')->setBody('status=' . urlencode($tweetText))->setAllHeaders(['Authorization' => $authorizationHeader, 'Content-Type' => 'application/x-www-form-urlencoded']);
     /** @var HttpResponse $result */
     $result = (yield $this->httpClient->request($request));
     $tweetInfo = json_decode($result->getBody(), true);
     $tweetUri = 'https://twitter.com/' . $tweetInfo['user']['screen_name'] . '/status/' . $tweetInfo['id_str'];
     return $this->chatClient->postMessage($command->getRoom(), $tweetUri);
 }
Beispiel #6
0
 private function setReminder(Command $command, string $commandName) : Promise
 {
     return resolve(function () use($command, $commandName) {
         $intervalParser = new IntervalParser();
         switch ($commandName) {
             case 'in':
                 $parameters = $intervalParser->normalizeTimeInterval(implode(" ", $command->getParameters()));
                 $expression = IntervalParser::$intervalSeparatorDefinitions . IntervalParser::$intervalWithTrailingData;
                 if (preg_match($expression, $parameters, $matches)) {
                     $time = $matches['interval'] ?? false;
                     $text = $matches['trailing'] ?? false;
                 }
                 break;
             case 'at':
                 $time = $command->getParameter(0) ?? false;
                 // 24hrs
                 if ($time && preg_match(self::TIME_FORMAT_REGEX, $time)) {
                     // maybe @TODO support !!at monday next week remind?
                     $text = implode(" ", array_diff($command->getParameters(), array($time)));
                 }
                 break;
             case 'reminder':
                 $parameters = implode(" ", $command->getParameters());
                 if (!preg_match(self::REMINDER_REGEX, $parameters, $matches)) {
                     return $this->chatClient->postMessage($command->getRoom(), self::USAGE);
                 }
                 $time = $matches[2] ?? '';
                 $text = $matches[1] ?? false;
                 if ($time !== '') {
                     $time = $intervalParser->normalizeTimeInterval($time);
                 }
                 break;
         }
         if (!isset($time) || !$time) {
             return $this->chatClient->postMessage($command->getRoom(), "Have a look at the time again, yo!");
         }
         if (!isset($text) || !$text) {
             return $this->chatClient->postMessage($command->getRoom(), self::USAGE);
         }
         $timestamp = strtotime($time) ?: strtotime("+{$time}");
         // false|int
         if (!$timestamp) {
             return $this->chatClient->postMessage($command->getRoom(), "Have a look at the time again, yo!");
         }
         $key = (string) $command->getId();
         $value = ['id' => $key, 'text' => $text, 'delay' => $time, 'userId' => $command->getUserId(), 'username' => $command->getUserName(), 'timestamp' => $timestamp];
         $seconds = $timestamp - time();
         if ($seconds <= 0) {
             return $this->chatClient->postReply($command, "I guess I'm late: " . $text);
         }
         if ((yield $this->storage->set($key, $value, $command->getRoom()))) {
             $watcher = once(function () use($command, $value, $key) {
                 (yield $this->storage->unset($key, $command->getRoom()));
                 return $this->chatClient->postReply($command, $value['text']);
             }, $seconds * 1000);
             $this->watchers[] = $watcher;
             return $this->chatClient->postMessage($command->getRoom(), "Reminder set.");
         }
         return $this->chatClient->postMessage($command->getRoom(), "Dunno what happened but I couldn't set the reminder.");
     });
 }
Beispiel #7
0
 private function invokeHandlerForCommand(Command $command) : Promise
 {
     $roomIdent = $command->getRoom()->getIdentifier()->getIdentString();
     $commandName = $command->getCommandName();
     if (!isset($this->commandMap[$roomIdent][$commandName])) {
         return new Success();
     }
     return resolve(function () use($command, $roomIdent, $commandName) {
         $userId = $command->getUserId();
         $userIsBanned = (yield $this->banStorage->isBanned($command->getRoom(), $userId));
         if ($userIsBanned) {
             $this->logger->log(Level::DEBUG, "User #{$userId} is banned, ignoring event #{$command->getEvent()->getId()} for plugin command endpoints" . " (command: {$commandName})");
             return;
         }
         /** @var Plugin $plugin */
         /** @var PluginCommandEndpoint $endpoint */
         list($plugin, $endpoint) = $this->commandMap[$roomIdent][$commandName];
         // just a sanity check, shouldn't ever be false but in case something goes horribly wrong
         if (!$this->isPluginEnabledForRoom($plugin, $command->getRoom())) {
             $this->logger->log(Level::DEBUG, "Command {$commandName} still present for {$roomIdent} but plugin {$plugin->getName()}" . " is disabled! (endpoint: {$endpoint->getName()})");
             return;
         }
         (yield $this->invokeCallbackAsPromise($endpoint->getCallback(), $command));
     });
 }
Beispiel #8
0
 public function dadGreet(Command $command)
 {
     $room = $command->getRoom();
     switch ($command->getParameter(0)) {
         case 'on':
             if (!(yield $this->admin->isAdmin($room, $command->getUserId()))) {
                 return $this->chatClient->postReply($command, "I'm sorry Dave, I'm afraid I can't do that");
             }
             if (preg_match('#[0-9]+#', $command->getParameter(1))) {
                 if (1 > ($frequency = (int) $command->getParameter(1))) {
                     return $this->chatClient->postReply($command, 'Frequency cannot be less than 1');
                 }
                 yield from $this->setDadGreetFrequency($room, $frequency);
             }
             yield from $this->setDadGreetEnabled($room, true);
             return $this->chatClient->postMessage($room, 'Dad greeting is now enabled with a frequency of ' . (yield from $this->getDadGreetFrequency($room)));
         case 'off':
             if (!(yield $this->admin->isAdmin($room, $command->getUserId()))) {
                 return $this->chatClient->postReply($command, "I'm sorry Dave, I'm afraid I can't do that");
             }
             yield from $this->setDadGreetEnabled($room, false);
             return $this->chatClient->postMessage($room, 'Dad greeting is now disabled');
         case 'status':
             $state = (yield from $this->isDadGreetEnabled($room)) ? 'enabled with a frequency of ' . (yield from $this->getDadGreetFrequency($room)) : 'disabled';
             return $this->chatClient->postMessage($room, 'Dad greeting is currently ' . $state);
     }
     return $this->chatClient->postReply($command, 'Syntax: ' . $command->getCommandName() . ' on|off|status [frequency]');
 }
Beispiel #9
0
 public function tweet(Command $command)
 {
     $room = $command->getRoom();
     if (!(yield $this->admin->isAdmin($room, $command->getUserId()))) {
         return $this->chatClient->postReply($command, "I'm sorry Dave, I'm afraid I can't do that");
     }
     try {
         /** @var TwitterClient $client */
         $client = (yield from $this->getClientForRoom($room));
         // do this first to make sure it's worth going further
         $message = (yield from $this->getRawMessage($room, $command->getParameter(0)));
         $request = (yield from $this->buildTwitterRequest($room, $message));
         $result = (yield $client->request($request));
         $tweetURL = sprintf('https://twitter.com/%s/status/%s', $result['user']['screen_name'], $result['id_str']);
         return $this->chatClient->postMessage($room, $tweetURL);
     } catch (NotConfiguredException $e) {
         return $this->chatClient->postReply($command, "I'm not currently configured for tweeting :-(");
     } catch (LibXMLFatalErrorException $e) {
         return $this->chatClient->postReply($command, 'Totally failed to parse the chat message :-(');
     } catch (MessageIDNotFoundException $e) {
         return $this->chatClient->postReply($command, 'I need a chat message link to tweet');
     } catch (TweetIDNotFoundException $e) {
         return $this->chatClient->postReply($command, "That looks like a retweet but I can't find the tweet ID :-S");
     } catch (TextProcessingFailedException $e) {
         return $this->chatClient->postReply($command, "Processing the message text failed :-S");
     } catch (TweetLengthLimitExceededException $e) {
         return $this->chatClient->postReply($command, "Boo! The message exceeds the 140 character limit. :-(");
     } catch (TwitterRequestFailedException $e) {
         return $this->chatClient->postReply($command, 'Posting to Twitter failed :-( ' . $e->getMessage());
     }
 }
Beispiel #10
0
 private function alias(CommandMessage $command) : \Generator
 {
     $room = $command->getRoom();
     if (!(yield $this->adminStorage->isAdmin($room, $command->getUserId()))) {
         return $this->chatClient->postReply($command, self::message('user_not_admin'));
     }
     if (!$command->hasParameters(2)) {
         return $this->chatClient->postReply($command, self::message('syntax'));
     }
     $newCmd = $command->getParameter(1);
     $oldCmd = $command->getParameter(2);
     if (in_array($newCmd, $this->builtInCommandManager->getRegisteredCommands())) {
         return $this->chatClient->postReply($command, self::message('command_built_in', $newCmd));
     }
     if ($this->pluginManager->isCommandMappedForRoom($room, $newCmd)) {
         return $this->chatClient->postReply($command, self::message('command_already_mapped', $newCmd));
     }
     if (in_array($oldCmd, $this->builtInCommandManager->getRegisteredCommands())) {
         return $this->chatClient->postReply($command, self::message('command_built_in', $oldCmd));
     }
     if (!$this->pluginManager->isCommandMappedForRoom($room, $oldCmd)) {
         return $this->chatClient->postReply($command, self::message('command_not_mapped', $oldCmd));
     }
     $mapping = $this->pluginManager->getMappedCommandsForRoom($room)[$oldCmd];
     if (!$this->pluginManager->isPluginEnabledForRoom($mapping['plugin_name'], $room)) {
         return $this->chatClient->postReply($command, self::message('plugin_not_enabled', $mapping['plugin_name']));
     }
     (yield $this->pluginManager->mapCommandForRoom($room, $mapping['plugin_name'], $mapping['endpoint_name'], $newCmd));
     return $this->chatClient->postMessage($room, self::message('command_map_success', $newCmd, $mapping['plugin_name'], $mapping['endpoint_name']));
 }