private function execute(CommandMessage $command) : \Generator { if (!(yield $command->getRoom()->isApproved())) { return; } return $this->chatClient->postReply($command, sprintf('I have been running for %s, since %s', dateinterval_to_string((new \DateTime())->diff($this->startTime)), $this->startTime->format('Y-m-d H:i:s'))); }
public function scrabble(Command $command) : Promise { if ($command->hasParameters() === false) { return $this->chatClient->postMessage($command->getRoom(), self::USAGE); } return $this->chatClient->postReply($command, $this->formatScores($this->calculateScores($this->getScorableWords($command->getParameters())))); }
private function getPostBody(Command $command) : string { $parameters = $command->getParameters(); if (count($parameters) < 2) { throw new \RuntimeException('Usage: `!!post [options] postdata url`'); } return $parameters[count($parameters) - 2]; }
public function search(Command $command) : \Generator { if (!$command->hasParameters()) { return new Success(); } $response = (yield $this->httpClient->request('http://www.imdb.com/xml/find?xml=1&nr=1&tt=on&q=' . rawurlencode(implode(' ', $command->getParameters())))); return $this->chatClient->postMessage($command->getRoom(), $this->getMessage($response)); }
public function questionify(CommandMessage $command) { $text = (yield $this->messageResolver->resolveMessageText($command->getRoom(), $command->getText())); if (preg_match('/\\?\\s*$/', $text)) { return $this->chatClient->postReply($command, 'That\'s already a question'); } return $this->chatClient->postMessage($command->getRoom(), rtrim($text) . '?'); }
public function lmgtfy(Command $command) { $text = $command->getText(); if ((bool) preg_match('~^http://chat\\.stackoverflow\\.com/transcript/message/(\\d+)(#\\d+)?$~', $text)) { $text = (yield $this->messageResolver->resolveMessageText($command->getRoom(), $text)); } return $this->chatClient->postReply($command, $this->getResponse($text)); }
public function is(Command $command) : Promise { $reply = random_int(0, 1) ? "yes" : "no"; if (!random_int(0, 15)) { $reply = "dunno"; } $reply = $this->getRandomReply($reply); return $this->chatClient->postMessage($command->getRoom(), $reply); }
public function run(Command $command) : Generator { if (!$command->hasParameters()) { return $this->chatClient->postMessage($command->getRoom(), self::USAGE); } $form = (new FormBody())->addField("exp", implode(" ", $command->getParameters())); $request = (new Request())->setMethod("POST")->setUri("https://tryhaskell.org/eval")->setBody($form); $response = (yield $this->httpClient->request($request)); return $this->chatClient->postMessage($command->getRoom(), $this->getMessage($response)); }
public function random(Command $command) : \Generator { if (!$command->hasParameters()) { return new Success(); } /** @var HttpResponse $response */ $response = (yield $this->httpClient->request(self::API_BASE_URL . 'v1/gifs/random?' . http_build_query(['api_key' => $this->apiKey, 'rating' => $this->rating, 'tag' => implode(' ', $command->getParameters())]))); $result = json_decode($response->getBody(), true); return $this->chatClient->postMessage($command->getRoom(), $this->getMessage($result)); }
public function search(Command $command) : \Generator { if (!$command->hasParameters()) { return new Success(); } /** @var HttpResponse $response */ $response = (yield $this->httpClient->request('http://api.urbandictionary.com/v0/define?term=' . rawurlencode(implode(' ', $command->getParameters())))); $result = json_decode($response->getBody(), true); return $this->chatClient->postMessage($command->getRoom(), $this->getMessage($result), PostFlags::TRUNCATE); }
public function search(Command $command) : \Generator { if (!$command->hasParameters()) { return new Success(); } $uri = "https://www.google.com/search?q=site:xkcd.com+intitle%3a%22xkcd%3a+%22+" . urlencode(implode(' ', $command->getParameters())); /** @var HttpResponse $response */ $response = (yield $this->httpClient->request($uri)); if ($response->getStatus() !== 200) { return $this->chatClient->postMessage($command->getRoom(), "Useless error message here so debugging this is harder than needed."); } $dom = domdocument_load_html($response->getBody()); $nodes = (new \DOMXPath($dom))->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' g ')]/h3/a"); /** @var \DOMElement $node */ foreach ($nodes as $node) { if (preg_match('~^/url\\?q=(https://xkcd\\.com/\\d+/)~', $node->getAttribute('href'), $matches)) { return $this->chatClient->postMessage($command->getRoom(), $matches[1]); } } if (preg_match('/^(\\d+)$/', trim(implode(' ', $command->getParameters())), $matches) !== 1) { return $this->chatClient->postMessage($command->getRoom(), self::NOT_FOUND_COMIC); } /** @var HttpResponse $response */ $response = (yield $this->httpClient->request('https://xkcd.com/' . $matches[1])); if ($response->getStatus() !== 200) { return $this->chatClient->postMessage($command->getRoom(), self::NOT_FOUND_COMIC); } return $this->chatClient->postMessage($command->getRoom(), 'https://xkcd.com/' . $matches[1]); }
private function getVersion(CommandMessage $command) : \Generator { if (!(yield $command->getRoom()->isApproved())) { return; } $version = (new SebastianVersion(VERSION, APP_BASE))->getVersion(); $messageText = preg_replace_callback('@v([0-9.]+)(?:-\\d+-g([0-9a-f]+))?@', function ($match) { return sprintf("[%s](%s)", $match[0], empty($match[2]) ? "https://github.com/Room-11/Jeeves/tree/v" . $match[1] : "https://github.com/Room-11/Jeeves/commit/" . $match[2]); }, $version); (yield $this->chatClient->postMessage($command->getRoom(), $messageText)); }
public function search(Command $command) : \Generator { if (!$command->hasParameters()) { return new Success(); } /** @var HttpResponse $response */ $response = (yield $this->httpClient->request('https://developer.mozilla.org/en-US/search.json?highlight=false&q=' . rawurlencode(implode('%20', $command->getParameters())))); $result = json_decode($response->getBody(), true); if (!isset($result["documents"][0]["id"], $result["documents"][0]["url"])) { return $this->postNoResult($command); } return $this->postResult($command, $result["documents"][0]); }
protected function getCommitReference(Command $command, string $path) { list($user, $repo) = explode('/', $path, 2); /** @var HttpResponse $response */ $response = (yield $this->httpClient->request(self::BASE_URL . '/repos/' . urlencode($user) . '/' . urlencode($repo) . '/git/refs/heads/master')); if ($response->getStatus() !== 200) { return $this->chatClient->postMessage($command->getRoom(), "Failed to fetch repo for {$path}"); } $json = json_decode($response->getBody()); if (!isset($json->object->sha)) { return $this->chatClient->postMessage($command->getRoom(), "Failed to fetch reference SHA for {$path}"); } return $json->object->sha; }
public function search(Command $command) : \Generator { if (!$command->hasParameters()) { return new Success(); } /** @var HttpResponse $response */ $response = (yield $this->httpClient->request("https://man.freebsd.org/" . rawurlencode(implode("%20", $command->getParameters())))); $dom = domdocument_load_html($response->getBody()); $xpath = new \DOMXPath($dom); if (!$this->isFound($xpath)) { return $this->postNoResult($command); } return $this->postResult($command, $xpath, $response->getRequest()->getUri()); }
public function search(Command $command) : \Generator { if (!$command->hasParameters()) { return new Success(); } /** @var HttpResponse $response */ $response = (yield $this->makeAPIRequest(['titles' => implode(' ', $command->getParameters())])); $result = json_try_decode($response->getBody(), true); $firstHit = reset($result['query']['pages']); if (!isset($firstHit['pageid'])) { return $this->chatClient->postReply($command, 'Sorry I couldn\'t find that page.'); } $response = (yield $this->makeAPIRequest(['prop' => 'info', 'inprop' => 'url', 'pageids' => $firstHit['pageid']])); $page = json_try_decode($response->getBody(), true); return $this->chatClient->postMessage($command->getRoom(), $page['query']['pages'][$firstHit['pageid']]['canonicalurl']); }
public function search(Command $command) : \Generator { if (!$command->hasParameters()) { return $this->chatClient->postReply($command, 'Mhm, I need a film title you want me to look for.'); } $search = $command->getText(); $message = (yield $this->chatClient->postMessage($command->getRoom(), sprintf('_Looking for \'%s\' for you…_', $search))); $params = $this->buildTitleSearchParams($search); // Send it out. /** @var HttpResponse $response */ $response = (yield $this->httpClient->request(sprintf('%s?%s', self::OMDB_API_ENDPOINT, http_build_query($params)))); /** @var \stdClass $data */ $data = @json_decode($response->getBody()); if (!$data || $data->Response === 'False') { return $this->chatClient->postMessage($command->getRoom(), 'I couldn\'t find anything for that title.'); } $searchResults = []; foreach ($data->Search as $searchResult) { $searchResults[$searchResult->imdbID] = $searchResult; } // Only pick the top 3 results if needed. $searchResults = array_slice($searchResults, 0, 3, true); /** @var PostedMessage $chatMessage */ (yield $this->chatClient->editMessage($message, $this->formatSearchResults($searchResults))); $requests = []; // Send out multiple http requests to get film descriptions and ratings. foreach ($searchResults as $id => $searchResult) { $requests[$id] = sprintf('%s?%s', self::OMDB_API_ENDPOINT, http_build_query($this->buildTitleDescParams($id))); } // Wait until all requests are done, allow failures. $allRequests = \Amp\some($this->httpClient->requestMulti($requests)); list($errors, $responses) = (yield $allRequests); $descriptionResults = []; foreach ($responses as $key => $response) { $responseBody = @json_decode($response->getBody()); if (!$responseBody || $responseBody->Response === 'False') { continue; } $descriptionResults[$key] = $responseBody; } return $this->chatClient->editMessage($message, $this->formatSearchResults($searchResults, $descriptionResults)); }
public function search(Command $command) : \Generator { $info = explode('/', implode('/', $command->getParameters()), 2); if (count($info) !== 2) { return $this->chatClient->postReply($command, "Usage: `!!packagist vendor package`"); } list($vendor, $package) = $info; $url = 'https://packagist.org/packages/' . urlencode($vendor) . '/' . urldecode($package) . '.json'; try { /** @var HttpResponse $response */ $response = (yield $this->httpClient->request($url)); if ($response->getStatus() !== 200) { $response = (yield from $this->getResultFromSearchFallback($vendor, $package)); } $data = json_try_decode($response->getBody()); return $this->chatClient->postMessage($command->getRoom(), sprintf("[ [%s](%s) ] %s", $data->package->name, $data->package->repository, $data->package->description)); } catch (\Throwable $e) { return $this->chatClient->postReply($command, 'No matching packages found'); } }
private function execute(CommandMessage $command) { if (!(yield $command->getRoom()->isApproved())) { return; } if (!in_array($command->getParameter(0), self::ACTIONS, true)) { return; } if ($command->getParameter(0) === "list") { return yield from $this->list($command); } if (!(yield $this->storage->isAdmin($command->getRoom(), $command->getUserId()))) { return $this->chatClient->postReply($command, "I'm sorry Dave, I'm afraid I can't do that"); } switch ($command->getParameter(0)) { case 'add': return yield from $this->add($command, (int) $command->getParameter(1)); case 'remove': return yield from $this->remove($command, (int) $command->getParameter(1)); } throw new \LogicException('Operation ' . $command->getParameter(0) . ' was considered valid but not handled??'); }
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}"); }
public function getRFC(Command $command) { $rfc = $command->getParameter(0); if ($rfc === null) { // e.g.: !!rfc pipe-operator return $this->chatClient->postMessage($command->getRoom(), "RFC id required"); } $uri = self::BASE_URI . '/' . urlencode($rfc); /** @var HttpResponse $response */ $response = (yield $this->httpClient->request($uri)); if ($response->getStatus() !== 200) { return $this->chatClient->postMessage($command->getRoom(), "Nope, we can't have nice things."); } $votes = self::parseVotes($response->getBody()); if (empty($votes)) { return $this->chatClient->postMessage($command->getRoom(), "No votes found"); } $messages = []; foreach ($votes as $id => $vote) { $breakdown = []; $total = array_sum($vote['votes']); if ($total > 0) { foreach ($vote['votes'] as $option => $value) { $breakdown[] = sprintf("%s (%d: %d%%)", $option, $value, 100 * $value / $total); } } $messages[] = ['name' => $vote['name'], 'href' => $uri . '#' . $id, 'breakdown' => implode(', ', $breakdown)]; } if (count($messages) === 1) { return $this->chatClient->postMessage($command->getRoom(), sprintf("[tag:rfc-vote] [%s](%s) %s", $messages[0]['name'], $messages[0]['href'], $messages[0]['breakdown'])); } $message = implode("\n", array_map(function ($message) { return sprintf('%s %s - %s (%s)', self::BULLET, $message['name'], $message['breakdown'], $message['href']); }, $messages)); return $this->chatClient->postMessage($command->getRoom(), $message); }
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}"); } }); }
/** * Example: * !!github Room-11/Jeeves * * [tag:github-repo] [Room-11/Jeeves](https://github.com/Room-11/Jeeves) Chatbot attempt - * - Watchers: 14, Forks: 15, Last Pushed: 2016-05-26T08:57:41Z * * @param Command $command * @param string $path * @return \Generator */ protected function repo(Command $command, string $path) : \Generator { list($user, $repo) = explode('/', $path, 2); /** @var HttpResponse $response */ $response = (yield $this->httpClient->request('https://api.github.com/repos/' . urlencode($user) . '/' . urlencode($repo))); if ($response->getStatus() !== 200) { return $this->chatClient->postMessage($command->getRoom(), "Failed fetching repo for {$path}"); } $json = json_decode($response->getBody()); if (!isset($json->id)) { return $this->chatClient->postMessage($command->getRoom(), "Unknown repo {$path}"); } return $this->chatClient->postMessage($command->getRoom(), sprintf("[tag:github-repo] [%s](%s) %s - Watchers: %d, Forks: %d, Last Push: %s", $json->full_name, $json->html_url, $json->description, $json->watchers, $json->forks, $json->pushed_at)); }
public function fetch(Command $command) : \Generator { $response = (yield $this->httpClient->request(self::API_URL)); return $this->chatClient->postMessage($command->getRoom(), $this->getMessage($response)); }
public function search(Command $command) : \Generator { if (!$command->hasParameters()) { return new Success(); } $text = implode(' ', $command->getParameters()); $searchTerm = (yield $this->messageResolver->resolveMessageText($command->getRoom(), $text)); $uri = $this->getSearchURL($searchTerm); $request = (new HttpRequest())->setMethod('GET')->setUri($uri)->setHeader('User-Agent', self::USER_AGENT); /** @var HttpResponse $response */ $response = (yield $this->httpClient->request($request)); if ($response->getStatus() !== 200) { return $this->chatClient->postMessage($command->getRoom(), "Google responded with {$response->getStatus()}"); } if (preg_match('#charset\\s*=\\s*([^;]+)#i', trim(implode(', ', $response->getHeader('Content-Type'))), $match) && !preg_match('/' . preg_quote(self::ENCODING, '/') . '/i', $match[1])) { $body = iconv($match[1], self::ENCODING, $response->getBody()); } if (empty($body)) { $body = $response->getBody(); } $dom = domdocument_load_html($body); $xpath = new \DOMXPath($dom); $nodes = $this->getResultNodes($xpath); if ($nodes->length === 0) { return $this->postNoResultsMessage($command); } $searchResults = $this->getSearchResults($nodes, $xpath); $postMessage = $this->getPostMessage($searchResults, $uri, $searchTerm); return $this->chatClient->postMessage($command->getRoom(), $postMessage); }
public function toLanguage(Command $command, string $toLanguage = null) : \Generator { $params = $command->getParameters(); if ($params[0] === 'list') { return $this->postSupportedLanguagesList($command->getRoom()); } $toLanguage = $toLanguage ?? array_shift($params); if (null === ($toLanguageCode = $this->getLanguageCode($toLanguage ?? array_shift($params)))) { return $this->chatClient->postReply($command, 'Sorry, I don\'t speak ' . $toLanguage); } $fromLanguageCode = null; if (preg_match('#^--from(?:=(.+))?$#', $params[0] ?? '', $match)) { array_shift($params); $fromLanguage = empty($match[1]) ? array_shift($params) : $match[1]; if (null === ($fromLanguageCode = $this->getLanguageCode($fromLanguage))) { return $this->chatClient->postReply($command, 'Sorry, I don\'t speak ' . $fromLanguage); } } if (count($params) < 1) { return $this->chatClient->postReply($command, 'The empty string is the same in every language'); } $text = (yield from $this->getTextFromArguments($command->getRoom(), $params)); $translation = (yield from $this->getTranslation($command->getRoom(), $text, $toLanguageCode, $fromLanguageCode)); return $this->chatClient->postMessage($command->getRoom(), $translation); }
public function trenslete(CommandMessage $command) { $text = (yield $this->messageResolver->resolveMessageText($command->getRoom(), $command->getText())); return $this->chatClient->postReply($command, $this->ruinPrepositions($text)); }
public function getExamples(Command $command) : Promise { $examples = "Examples: \n" . Chars::BULLET . " !!reminder foo at 18:00 \n" . Chars::BULLET . " With timezone: (ie. UTC-3) !!reminder foo at 18:00-3:00 \n" . Chars::BULLET . " !!reminder bar in 2 hours \n" . Chars::BULLET . " !!reminder unset 32901146 \n" . Chars::BULLET . " !!reminder list \n" . Chars::BULLET . " !!in 2 days 42 hours 42 minutes 42 seconds 42! \n" . Chars::BULLET . " !!at 22:00 Grab a beer!"; return resolve(function () use($command, $examples) { return $this->chatClient->postMessage($command->getRoom(), $examples); }); }
/** * Handle a command message * * @param Command $command * @return Promise */ public function handleCommand(Command $command) : Promise { if ($command->getParameter(0) === "list") { return $this->getSupportedCanonicals($command); } if (!in_array($command->getParameter(0), self::ACTIONS)) { return $this->getMessage($command, implode(" ", $command->getParameters())); } return resolve(function () use($command) { 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."); } switch ($command->getParameter(0)) { case 'add': return (yield $this->add($command, (string) $command->getParameter(1), (string) $command->getParameter(2))); case 'remove': return (yield $this->remove($command, (string) $command->getParameter(1))); case 'fire': return (yield $this->fire($command)); } }); }
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); }