├── LICENSE ├── README.md ├── composer.json ├── example.php ├── src └── HipChat │ └── HipChat.php └── tests └── HipChatPHPTest.php /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) HipChat, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # hipchat-php 2 | 3 | A PHP library for interacting with the [HipChat](http://hipchat.com) REST API. 4 | 5 | ## Composer Installation 6 | 7 | HipChat-PHP can be installed with Composer (http://getcomposer.org/). Add the following to your 8 | composer.json file. Composer will handle the autoloading. 9 | 10 | ```json 11 | { 12 | "require": { 13 | "hipchat/hipchat-php": ">=1.0.0" 14 | } 15 | } 16 | ``` 17 | 18 | ## Usage 19 | 20 | ```php 21 | $token = ''; 22 | $hc = new HipChat\HipChat($token); 23 | 24 | // list rooms 25 | foreach ($hc->get_rooms() as $room) { 26 | echo " - $room->room_id = $room->name\n"; 27 | } 28 | 29 | // send a message to the 'Development' room from 'API' 30 | $hc->message_room('Development', 'API', 'This is just a test message!'); 31 | ``` 32 | 33 | ## Testing 34 | 35 | You can test this library (and your API key) using the example.php script as follows. It should print a list of your rooms and users. 36 | 37 | ./example.php 38 | 39 | To test the library itself, run the PHPUnit tests: 40 | 41 | phpunit tests/ 42 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hipchat/hipchat-php", 3 | "type": "library", 4 | "description": "PHP library for HipChat", 5 | "keywords": ["hipchat"], 6 | "homepage": "http://github.com/hipchat/hipchat-php", 7 | "license": "MIT", 8 | "require": { 9 | "php": ">=5.3.0" 10 | }, 11 | "autoload": { 12 | "psr-0": { 13 | "HipChat": "src" 14 | } 15 | }, 16 | "authors": [ 17 | { 18 | "name": "HipChat", 19 | "email": "support@hipchat.com", 20 | "homepage": "https://www.hipchat.com", 21 | "role": "Company" 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /example.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php 2 | [target]\n"; 8 | die; 9 | } 10 | 11 | $token = $argv[1]; 12 | $target = isset($argv[2]) ? $argv[2] : 'https://api.hipchat.com'; 13 | $hc = new HipChat\HipChat($token, $target); 14 | 15 | echo "Testing HipChat API.\nTarget: $target\nToken: $token\n\n"; 16 | 17 | // get rooms 18 | echo "Rooms:\n"; 19 | try { 20 | $rooms = $hc->get_rooms(); 21 | foreach ($rooms as $room) { 22 | echo "Room $room->room_id\n"; 23 | echo " - Name: $room->name\n"; 24 | $room_data = $hc->get_room($room->room_id); 25 | echo " - Participants: ".count($room_data->participants)."\n"; 26 | } 27 | } catch (HipChat\HipChat_Exception $e) { 28 | echo "Oops! Error: ".$e->getMessage(); 29 | } 30 | 31 | // get users 32 | echo "\nUsers:\n"; 33 | try { 34 | $users = $hc->get_users(); 35 | foreach ($users as $user) { 36 | echo "User $user->user_id\n"; 37 | echo " - Name: $user->name\n"; 38 | echo " - Email: $user->email\n"; 39 | $user_data = $hc->get_user($user->user_id); 40 | echo " - Status: ".$user_data->status."\n"; 41 | } 42 | } catch (HipChat\HipChat_Exception $e) { 43 | echo "Oops! Error: ".$e->getMessage(); 44 | } 45 | -------------------------------------------------------------------------------- /src/HipChat/HipChat.php: -------------------------------------------------------------------------------- 1 | api_target = $api_target; 67 | $this->auth_token = $auth_token; 68 | $this->api_version = $api_version; 69 | } 70 | 71 | 72 | ///////////////////////////////////////////////////////////////////////////// 73 | // Room functions 74 | ///////////////////////////////////////////////////////////////////////////// 75 | 76 | /** 77 | * Get information about a room 78 | * 79 | * @see http://api.hipchat.com/docs/api/method/rooms/show 80 | */ 81 | public function get_room($room_id) { 82 | $response = $this->make_request('rooms/show', array( 83 | 'room_id' => $room_id 84 | )); 85 | return $response->room; 86 | } 87 | 88 | /** 89 | * Determine if the given room name or room id already exists. 90 | * 91 | * @param mixed $room_id 92 | * @return boolean 93 | */ 94 | public function room_exists($room_id) { 95 | try { 96 | $this->get_room($room_id); 97 | } 98 | catch (HipChat_Exception $e) { 99 | if ($e->code === self::STATUS_NOT_FOUND) { 100 | return false; 101 | } 102 | throw $e; 103 | } 104 | return true; 105 | } 106 | 107 | /** 108 | * Get list of rooms 109 | * 110 | * @see http://api.hipchat.com/docs/api/method/rooms/list 111 | */ 112 | public function get_rooms() { 113 | $response = $this->make_request('rooms/list'); 114 | return $response->rooms; 115 | } 116 | 117 | /** 118 | * Send a message to a room 119 | * 120 | * @see http://api.hipchat.com/docs/api/method/rooms/message 121 | */ 122 | public function message_room($room_id, $from, $message, $notify = false, 123 | $color = self::COLOR_YELLOW, 124 | $message_format = self::FORMAT_HTML) { 125 | $args = array( 126 | 'room_id' => $room_id, 127 | 'from' => $from, 128 | 'message' => $message, 129 | 'notify' => (int)$notify, 130 | 'color' => $color, 131 | 'message_format' => $message_format 132 | ); 133 | $response = $this->make_request('rooms/message', $args, 'POST'); 134 | return ($response->status == 'sent'); 135 | } 136 | 137 | /** 138 | * Get chat history for a room 139 | * 140 | * @see https://www.hipchat.com/docs/api/method/rooms/history 141 | */ 142 | public function get_rooms_history($room_id, $date = 'recent') { 143 | $response = $this->make_request('rooms/history', array( 144 | 'room_id' => $room_id, 145 | 'date' => $date 146 | )); 147 | return $response->messages; 148 | } 149 | 150 | /** 151 | * Set a room's topic 152 | * 153 | * @see http://api.hipchat.com/docs/api/method/rooms/topic 154 | */ 155 | public function set_room_topic($room_id, $topic, $from = null) { 156 | $args = array( 157 | 'room_id' => $room_id, 158 | 'topic' => $topic, 159 | ); 160 | 161 | if ($from) { 162 | $args['from'] = $from; 163 | } 164 | 165 | $response = $this->make_request('rooms/topic', $args, 'POST'); 166 | return ($response->status == 'ok'); 167 | } 168 | 169 | /** 170 | * Create a room 171 | * 172 | * @see http://api.hipchat.com/docs/api/method/rooms/create 173 | */ 174 | public function create_room($name, $owner_user_id = null, $privacy = null, $topic = null, $guest_access = null) { 175 | $args = array( 176 | 'name' => $name 177 | ); 178 | 179 | if ($owner_user_id) { 180 | $args['owner_user_id'] = $owner_user_id; 181 | } 182 | 183 | if ($privacy) { 184 | $args['privacy'] = $privacy; 185 | } 186 | 187 | if ($topic) { 188 | $args['topic'] = $topic; 189 | } 190 | 191 | if ($guest_access) { 192 | $args['guest_access'] = (int)$guest_access; 193 | } 194 | 195 | // Return the std object 196 | return $this->make_request('rooms/create', $args, 'POST'); 197 | } 198 | 199 | /** 200 | * Delete a room 201 | * 202 | * @see http://api.hipchat.com/docs/api/method/rooms/delete 203 | */ 204 | public function delete_room($room_id){ 205 | $args = array( 206 | 'room_id' => $room_id 207 | ); 208 | 209 | $response = $this->make_request('rooms/delete', $args, 'POST'); 210 | 211 | return ($response->deleted == 'true'); 212 | } 213 | 214 | ///////////////////////////////////////////////////////////////////////////// 215 | // User functions 216 | ///////////////////////////////////////////////////////////////////////////// 217 | 218 | /** 219 | * Get information about a user 220 | * 221 | * @see http://api.hipchat.com/docs/api/method/users/show 222 | */ 223 | public function get_user($user_id) { 224 | $response = $this->make_request('users/show', array( 225 | 'user_id' => $user_id 226 | )); 227 | return $response->user; 228 | } 229 | 230 | /** 231 | * Get list of users 232 | * 233 | * @see http://api.hipchat.com/docs/api/method/users/list 234 | */ 235 | public function get_users() { 236 | $response = $this->make_request('users/list'); 237 | return $response->users; 238 | } 239 | 240 | /** 241 | * Create a new user in your group. 242 | * 243 | * @see http://api.hipchat.com/docs/api/method/users/create 244 | */ 245 | public function create_user($email, $name, $mention_name = null, 246 | $title = null, $is_group_admin = 0, 247 | $password = null, $timezone = null) { 248 | $args = array( 249 | 'email' => $email, 250 | 'name' => $name, 251 | ); 252 | 253 | if ($mention_name) { 254 | $args['mention_name'] = $mention_name; 255 | } 256 | 257 | if ($title) { 258 | $args['title'] = $title; 259 | } 260 | 261 | if ($is_group_admin) { 262 | $args['is_group_admin'] = (int)$is_group_admin; 263 | } 264 | 265 | if ($password) { 266 | $args['password'] = $password; 267 | } 268 | 269 | // @see http://api.hipchat.com/docs/api/timezones 270 | if ($timezone) { 271 | $args['timezone'] = $timezone; 272 | } 273 | 274 | // Return the std object 275 | return $this->make_request('users/create', $args, 'POST'); 276 | } 277 | 278 | /** 279 | * Update a user. 280 | * 281 | * @see http://api.hipchat.com/docs/api/method/users/update 282 | */ 283 | public function update_user($user_id, $email = null, $name = null, 284 | $mention_name = null, $title = null, 285 | $is_group_admin = 0, $password = null, 286 | $timezone = null) { 287 | $args = array( 288 | 'user_id' => $user_id, 289 | ); 290 | 291 | if ($email) { 292 | $args['email'] = $email; 293 | } 294 | 295 | if ($name) { 296 | $args['name'] = $name; 297 | } 298 | 299 | if ($mention_name) { 300 | $args['mention_name'] = $mention_name; 301 | } 302 | 303 | if ($title) { 304 | $args['title'] = $title; 305 | } 306 | 307 | if ($is_group_admin) { 308 | $args['is_group_admin'] = (int)$is_group_admin; 309 | } 310 | 311 | if ($password) { 312 | $args['password'] = $password; 313 | } 314 | 315 | // @see http://api.hipchat.com/docs/api/timezones 316 | if ($timezone) { 317 | $args['timezone'] = $timezone; 318 | } 319 | 320 | // Return the std object 321 | return $this->make_request('users/update', $args, 'POST'); 322 | } 323 | 324 | /** 325 | * Delete a user. 326 | * 327 | * @see http://api.hipchat.com/docs/api/method/users/delete 328 | */ 329 | public function delete_user($user_id) { 330 | return $this->make_request('users/delete', array( 331 | 'user_id' => $user_id 332 | ), 'POST'); 333 | } 334 | 335 | /** 336 | * Undelete a user. They will be sent an email requiring them to click a link to reactivate the account. 337 | * 338 | * @see http://api.hipchat.com/docs/api/method/users/undelete 339 | */ 340 | public function undelete_user($user_id) { 341 | return $this->make_request('users/undelete', array( 342 | 'user_id' => $user_id 343 | ), 'POST'); 344 | } 345 | 346 | ///////////////////////////////////////////////////////////////////////////// 347 | // Helper functions 348 | ///////////////////////////////////////////////////////////////////////////// 349 | 350 | /** 351 | * Performs a curl request 352 | * 353 | * @param $url URL to hit. 354 | * @param $post_data Data to send via POST. Leave null for GET request. 355 | * 356 | * @throws HipChat_Exception 357 | * @return string 358 | */ 359 | public function curl_request($url, $post_data = null) { 360 | 361 | if (is_array($post_data)) { 362 | $post_data = array_map(array($this, 'sanitize_curl_parameter'), $post_data); 363 | } 364 | 365 | $ch = curl_init($url); 366 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 367 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 368 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->request_timeout); 369 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verify_ssl); 370 | if (isset($this->proxy)) { 371 | curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); 372 | curl_setopt($ch, CURLOPT_PROXY, $this->proxy); 373 | } 374 | if (is_array($post_data)) { 375 | curl_setopt($ch, CURLOPT_POST, 1); 376 | curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); 377 | } 378 | $response = curl_exec($ch); 379 | 380 | // make sure we got a real response 381 | if (strlen($response) == 0) { 382 | $errno = curl_errno($ch); 383 | $error = curl_error($ch); 384 | throw new HipChat_Exception(self::STATUS_BAD_RESPONSE, 385 | "CURL error: $errno - $error", $url); 386 | } 387 | 388 | // make sure we got a 200 389 | $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE); 390 | if ($code != self::STATUS_OK) { 391 | throw new HipChat_Exception($code, 392 | "HTTP status code: $code, response=$response", $url); 393 | } 394 | 395 | curl_close($ch); 396 | 397 | return $response; 398 | } 399 | 400 | /** 401 | * Sanitizes the given value as cURL parameter. 402 | * 403 | * The first value may not be a "@". PHP would treat this as a file upload 404 | * 405 | * @link http://www.php.net/manual/en/function.curl-setopt.php CURLOPT_POSTFIELDS 406 | * 407 | * @param string $value 408 | * @return string 409 | */ 410 | private function sanitize_curl_parameter ($value) { 411 | 412 | if ((strlen($value) > 0) && ($value[0] === '@')) { 413 | return substr_replace($value, '@', 0, 1); 414 | } 415 | 416 | return $value; 417 | } 418 | 419 | /** 420 | * Make an API request using curl 421 | * 422 | * @param string $api_method Which API method to hit, like 'rooms/show'. 423 | * @param array $args Data to send. 424 | * @param string $http_method HTTP method (GET or POST). 425 | * 426 | * @throws HipChat_Exception 427 | * @return mixed 428 | */ 429 | public function make_request($api_method, $args = array(), 430 | $http_method = 'GET') { 431 | $args['format'] = 'json'; 432 | $args['auth_token'] = $this->auth_token; 433 | $url = "$this->api_target/$this->api_version/$api_method"; 434 | $post_data = null; 435 | 436 | // add args to url for GET 437 | if ($http_method == 'GET') { 438 | $url .= '?' . http_build_query($args); 439 | } else { 440 | $post_data = $args; 441 | } 442 | 443 | $response = $this->curl_request($url, $post_data); 444 | 445 | // make sure response is valid json 446 | $response = json_decode($response); 447 | if (!$response) { 448 | throw new HipChat_Exception(self::STATUS_BAD_RESPONSE, 449 | "Invalid JSON received: $response", $url); 450 | } 451 | 452 | return $response; 453 | } 454 | 455 | /** 456 | * Enable/disable verify_ssl. 457 | * This is useful when curl spits back ssl verification errors, most likely 458 | * due to outdated SSL CA bundle file on server. If you are able to, update 459 | * that CA bundle. If not, call this method with false for $bool param before 460 | * interacting with the API. 461 | * 462 | * @param bool $bool 463 | * @return bool 464 | * @link http://davidwalsh.name/php-ssl-curl-error 465 | */ 466 | public function set_verify_ssl($bool = true) { 467 | $this->verify_ssl = (bool)$bool; 468 | return $this->verify_ssl; 469 | } 470 | 471 | /** 472 | * Set an outbound proxy to use as a curl option 473 | * To disable proxy usage, set $proxy to null 474 | * 475 | * @param string $proxy 476 | */ 477 | public function set_proxy($proxy) { 478 | $this->proxy = $proxy; 479 | } 480 | 481 | /** 482 | * Change CURL request timeout. 483 | * You can change this value if you want to change request timeout toleration. 484 | * 485 | * @param int $timeout 486 | * 487 | * @return int 488 | */ 489 | public function set_request_timeout($timeout = 15) { 490 | $this->request_timeout = (int)$timeout; 491 | return $this->request_timeout; 492 | } 493 | } 494 | 495 | 496 | class HipChat_Exception extends \Exception { 497 | public $code; 498 | public function __construct($code, $info, $url) { 499 | $message = "HipChat API error: code=$code, info=$info, url=$url"; 500 | parent::__construct($message, (int)$code); 501 | } 502 | } 503 | -------------------------------------------------------------------------------- /tests/HipChatPHPTest.php: -------------------------------------------------------------------------------- 1 | target); 19 | $this->setExpectedException('HipChat\HipChat_Exception'); 20 | $hc->get_rooms(); 21 | } 22 | 23 | public function testBadTargetHost() { 24 | $bad_target = 'http://does-not-exist.hipchat.com'; 25 | $hc = new HipChat\HipChat('hipchat-php-test-token', $bad_target); 26 | $this->setExpectedException('HipChat\HipChat_Exception'); 27 | $hc->get_rooms(); 28 | } 29 | 30 | public function testBadApiMethod() { 31 | $hc = new HipChat\HipChat('hipchat-php-test-token', $this->target); 32 | $this->setExpectedException('HipChat\HipChat_Exception'); 33 | $hc->make_request('bad/method'); 34 | } 35 | 36 | 37 | 38 | /** 39 | * Tests for a mention at the first position in the message. 40 | * 41 | * In PHP, curl uses the syntax "@test.php" to send *the file* 42 | * test.php via curl. 43 | * 44 | * This test should actually just work (i.e. not throwing an exception) 45 | * 46 | * @link http://www.php.net/manual/en/function.curl-setopt.php see reference for CURLOPT_POSTFIELDS 47 | */ 48 | public function testMentionAtFirstPosition () 49 | { 50 | $hc = new HipChat\HipChat('hipchat-php-test-token', $this->target); 51 | $hc->message_room(123, '@sender', '@test test'); 52 | } 53 | 54 | } 55 | --------------------------------------------------------------------------------