hipchat-1.6.0/0000755000004100000410000000000013312114126013160 5ustar www-datawww-datahipchat-1.6.0/.travis.yml0000644000004100000410000000036613312114126015276 0ustar www-datawww-datalanguage: ruby before_install: # Travis bundler versions are quite out of date and can cause install errors # see: https://github.com/rubygems/rubygems/issues/1419 - gem update bundler rvm: - 2.0.0 - 2.1 - 2.2.6 - 2.3.3 - 2.4.0 hipchat-1.6.0/hipchat.gemspec0000644000004100000410000000267613312114126016160 0ustar www-datawww-data# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'hipchat/version' Gem::Specification.new do |spec| spec.name = "hipchat" spec.version = HipChat::VERSION spec.authors = ["HipChat/Atlassian"] spec.email = ["support@hipchat.com"] spec.description = %q{Ruby library to interact with HipChat} spec.summary = %q{Ruby library to interact with HipChat} spec.homepage = "https://github.com/hipchat/hipchat-rb" spec.license = "MIT" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.required_ruby_version = '>= 2.0.0' spec.add_dependency "httparty" spec.add_dependency "mimemagic" spec.add_development_dependency "rspec", "~> 3.0" spec.add_development_dependency "rr" spec.add_development_dependency "bundler", "~> 1.14.0" spec.add_development_dependency "rake" spec.add_development_dependency "webmock", "> 1.22.6" spec.add_development_dependency "addressable", "= 2.4.0" spec.add_development_dependency "term-ansicolor", "~> 1.4.0" spec.add_development_dependency "json", "> 1.8.4" spec.add_development_dependency 'rdoc', '> 2.4.2' spec.add_development_dependency 'tins', '~> 1.6.0' spec.add_development_dependency 'coveralls' end hipchat-1.6.0/spec/0000755000004100000410000000000013312114126014112 5ustar www-datawww-datahipchat-1.6.0/spec/hipchat_error_handler_spec.rb0000644000004100000410000001143313312114126022001 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/spec_helper') describe HipChat::ErrorHandler do let(:body) { { error: { code: code, message: 'any', type: 'any' } } } let(:request) { HTTParty::Request.new(Net::HTTP::Get, 'http://foo.com/') } let(:response) { HTTParty::Response.new(request, response_object, lambda { body }) } let(:room_id) { 'Hipchat' } before do allow(response_object).to receive_messages(body: body.to_json) end describe 'response_code_to_exception_for' do subject { HipChat::ErrorHandler.response_code_to_exception_for(:room, room_id, response) } context 'success codes' do shared_examples 'the error handler' do it "does not raise an error" do expect { subject }.not_to raise_error end end context 'Hipchat API responds with success' do describe 'code 200' do let(:response_object) { Net::HTTPOK.new('1.1', code, '') } let(:code) { 200 } it_should_behave_like 'the error handler' end describe 'code 201' do let(:response_object) { Net::HTTPCreated.new('1.1', code, '') } let(:code) { 201 } it_should_behave_like 'the error handler' end describe 'code 202' do let(:response_object) { Net::HTTPAccepted.new('1.1', code, '') } let(:code) { 202 } it_should_behave_like 'the error handler' end describe 'code 204' do let(:response_object) { Net::HTTPNoContent.new('1.1', code, '') } let(:code) { 204 } it_should_behave_like 'the error handler' end end end context 'failure codes' do shared_examples 'the error handler' do it "raises the correct client error" do expect { subject } .to raise_error(client_error) do |error| expect(error.message) .to match message end end end context 'Hipchat API responds with Not Found' do let(:response_object) { Net::HTTPNotFound.new('1.1', code, '') } let(:client_error) { HipChat::UnknownRoom } let(:message) { "Unknown room: `#{room_id}\':\nResponse: #{body.to_json}" } describe 'code 404' do let(:code) { 404 } it_should_behave_like 'the error handler' end end context 'Hipchat API responds with Unauthorized' do let(:response_object) { Net::HTTPUnauthorized.new('1.1', code, '') } let(:client_error) { HipChat::Unauthorized } let(:message) { "Access denied to room `#{room_id}\':\nResponse: #{body.to_json}" } describe 'code 401' do let(:code) { 401 } it_should_behave_like 'the error handler' end describe 'code 403' do let(:code) { 403 } it_should_behave_like 'the error handler' end end context 'Hipchat API responds with Bad Request' do let(:response_object) { Net::HTTPBadRequest.new('1.1', code, '') } let(:client_error) { HipChat::BadRequest } let(:message) { "The request was invalid. You may be missing a required argument or provided bad data. path:http://foo.com/ method:Net::HTTP::Get:\nResponse: #{body.to_json}" } describe 'code 400' do let(:code) { 400 } it_should_behave_like 'the error handler' end end context 'Hipchat API responds with MethodNotAllowed' do let(:response_object) { Net::HTTPMethodNotAllowed.new('1.1', code, '') } let(:client_error) { HipChat::MethodNotAllowed } let(:message) { "You requested an invalid method. path:http://foo.com/ method:Net::HTTP::Get:\nResponse: #{body.to_json}" } describe 'code 405' do let(:code) { 405 } it_should_behave_like 'the error handler' end end context 'Hipchat API responds with TooManyRequests' do let(:response_object) { Net::HTTPTooManyRequests.new('1.1', code, '') } let(:client_error) { HipChat::TooManyRequests } let(:message) { "You have exceeded the rate limit. `https://www.hipchat.com/docs/apiv2/rate_limiting`:\nResponse: #{body.to_json}" } describe 'code 429' do let(:code) { 429 } it_should_behave_like 'the error handler' end end context 'Hipchat API responds with an unknown response code' do let(:response_object) { Net::HTTPBadGateway.new('1.1', code, '') } let(:client_error) { HipChat::UnknownResponseCode } let(:message) { "Unexpected 502 for room `#{room_id}\'" } describe 'code 502' do let(:code) { 502 } it_should_behave_like 'the error handler' end end end end end hipchat-1.6.0/spec/spec.opts0000644000004100000410000000001013312114126015742 0ustar www-datawww-data--color hipchat-1.6.0/spec/hipchat_api_v1_spec.rb0000644000004100000410000001564113312114126020337 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/spec_helper') describe "HipChat (API V1)" do subject { HipChat::Client.new("blah", :api_version => @api_version) } let(:room) { subject["Hipchat"] } describe "#history" do include_context "HipChatV1" it "is successful without custom options" do mock_successful_history() expect(room.history()).to be_truthy end it "is successful with custom options" do mock_successful_history(:timezone => 'America/Los_Angeles', :date => '2010-11-19', :'max-results' => 10, :'start-index' => 10, :'end-date' => '2010-11-19') expect(room.history(:timezone => 'America/Los_Angeles', :date => '2010-11-19', :'max-results' => 10, :'start-index' => 10, :'end-date' => '2010-11-19')).to be_truthy end it "is successful from fetched room" do mock_successful_rooms mock_successful_history expect(subject.rooms).to be_truthy expect(subject.rooms.first.history).to be_truthy end it "fails when the room doen't exist" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect { room.history }.to raise_error(HipChat::UnknownRoom) end it "fails when we're not allowed to do so" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect { room.history }.to raise_error(HipChat::Unauthorized) end it "fails if we get an unknown response code" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect { room.history }.to raise_error(HipChat::Unauthorized) end end describe "#topic" do include_context "HipChatV1" it "is successful without custom options" do mock_successful_topic_change("Nice topic") expect(room.topic("Nice topic")).to be_truthy end it "is successful with a custom from" do mock_successful_topic_change("Nice topic", :from => "Me") expect(room.topic("Nice topic", :from => "Me")).to be_truthy end it "fails when the room doesn't exist" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect { room.topic "" }.to raise_error(HipChat::UnknownRoom) end it "fails when we're not allowed to do so" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect { room.topic "" }.to raise_error(HipChat::Unauthorized) end it "fails if we get an unknown response code" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect { room.topic "" }.to raise_error(HipChat::Unauthorized) end end describe "#delete_room" do include_context "HipChatV1" it "successfully" do mock_successful_delete_room("Hipchat") expect(room.delete_room).to be_truthy end it "missing room" do mock_delete_missing_room("Hipchat") expect do room.delete_room end.to raise_exception(HipChat::UnknownRoom) end end describe "#send" do include_context "HipChatV1" it "successfully without custom options" do mock_successful_send 'Dude', 'Hello world' expect(room.send("Dude", "Hello world")).to be_truthy end it "successfully with notifications on as option" do mock_successful_send 'Dude', 'Hello world', :notify => 1 expect(room.send("Dude", "Hello world", :notify => 1)).to be_truthy end it "successfully with custom color" do mock_successful_send 'Dude', 'Hello world', :color => 'red' expect(room.send("Dude", "Hello world", :color => 'red')).to be_truthy end it "successfully with text message_format" do mock_successful_send 'Dude', 'Hello world', :message_format => 'text' expect(room.send("Dude", "Hello world", :message_format => 'text')).to be_truthy end it "but fails when the room doesn't exist" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect { room.send "", "" }.to raise_error(HipChat::UnknownRoom) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect { room.send "", "" }.to raise_error(HipChat::Unauthorized) end it "but fails if the username is more than 15 chars" do expect { room.send "a very long username here", "a message" }.to raise_error(HipChat::UsernameTooLong) end it "but fails if we get an unknown response code" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect { room.send "", "" }.to raise_error(HipChat::Unauthorized) end end describe "#create" do include_context "HipChatV1" it "successfully with room name" do mock_successful_room_creation("A Room", :owner_user_id => "123456") expect(subject.create_room("A Room", {:owner_user_id => "123456"})).to be_truthy end it "successfully with custom parameters" do mock_successful_room_creation("A Room", {:owner_user_id => "123456", :privacy => "private", :guest_access => "1"}) expect(subject.create_room("A Room", {:owner_user_id => "123456", :privacy => "private", :guest_access =>true})).to be_truthy end it "but fails if we dont pass owner_user_id" do expect { subject.create_room("A Room", {:privacy => "private", :guest_access =>true}) }.to raise_error(HipChat::RoomMissingOwnerUserId) end end describe "#create_user" do include_context "HipChatV1" it "successfully with user name" do mock_successful_user_creation("A User", "email@example.com") expect(subject.create_user("A User", "email@example.com")).to be_truthy end it "successfully with custom parameters" do mock_successful_user_creation("A User", "email@example.com", {:title => "Super user", :password => "password", :is_group_admin => "true"}) expect(subject.create_user("A User", "email@example.com", {:title => "Super user", :password => "password", :is_group_admin =>true})).to be_truthy end it "but fail is name is longer then 50 char" do expect { subject.create_user("A User that is too long that I should fail right now", "email@example.com") }. to raise_error(HipChat::UsernameTooLong) end end describe "#send user message" do it "fails because API V1 doesn't support user operations" do expect { HipChat::Client.new("blah", :api_version => @api_version).user('12345678').send('nope') }. to raise_error(HipChat::InvalidApiVersion) end end describe "#create_webhook" it "fails because API V1 doesn't support webhooks" do expect { room.create_webhook('https://example.org/hooks/awesome', 'room_enter') }. to raise_error(HipChat::InvalidApiVersion) end end hipchat-1.6.0/spec/hipchat_spec.rb0000644000004100000410000000476613312114126017106 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/spec_helper') describe HipChat do describe 'http_proxy' do let(:proxy_user) { 'proxy_user' } let(:proxy_pass) { 'proxy_pass' } let(:proxy_host) { 'proxy.example.com' } let(:proxy_port) { 2649 } let(:proxy_url) { "http://#{proxy_user}:#{proxy_pass}@#{proxy_host}:#{proxy_port}" } context 'specified by option of constructor' do before do HipChat::Client.new("blah", :http_proxy => proxy_url) end subject { HipChat::Client.default_options } specify "Client's proxy settings should be changed" do expect(subject[:http_proxyaddr]).to eql(proxy_host) expect(subject[:http_proxyport]).to eql(proxy_port) expect(subject[:http_proxyuser]).to eql(proxy_user) expect(subject[:http_proxypass]).to eql(proxy_pass) end describe "Room class's proxy" do subject { HipChat::Room.default_options } specify "proxy settings should be changed" do expect(subject[:http_proxyaddr]).to eql(proxy_host) expect(subject[:http_proxyport]).to eql(proxy_port) expect(subject[:http_proxyuser]).to eql(proxy_user) expect(subject[:http_proxypass]).to eql(proxy_pass) end end end end describe 'options' do context "api_version" do it "defaults to a v2 client" do client = HipChat::Client.new("blah") expect(client[:example].api_version).to eql('v2') end it "when given 'v1' it registers a v1 client" do client = HipChat::Client.new("blah", :api_version => 'v1') expect(client[:example].api_version).to eql('v1') end it "when given 'v2' it registers a v2 client" do client = HipChat::Client.new("blah", :api_version => 'v2') expect(client[:example].api_version).to eql('v2') end it "when given '2' it raises an exception" do expect { HipChat::Client.new("blah", :api_version => '2') }. to raise_error(HipChat::InvalidApiVersion) end end context "server_url" do it "defaults to 'https://api.hipchat.com'" do client = HipChat::Client.new("derr") expect(client[:example].server_url).to eql('https://api.hipchat.com') end it "can be overridden to 'http://hipchat.example.com'" do client = HipChat::Client.new("derr", :server_url => 'http://hipchat.example.com') expect(client[:example].server_url).to eql('http://hipchat.example.com') end end end end hipchat-1.6.0/spec/example/0000755000004100000410000000000013312114126015545 5ustar www-datawww-datahipchat-1.6.0/spec/example/history.json0000644000004100000410000000144313312114126020143 0ustar www-datawww-dataHTTP/1.1 200 OK Content-Type: application/json { "messages": [ { "date": "2010-11-19T15:48:19-0800", "from": { "name": "Garret Heaton", "user_id": 10 }, "message": "Good morning! This is a regular message." }, { "date": "2010-11-19T15:49:44-0800", "from": { "name": "Garret Heaton", "user_id": 10 }, "file": { "name": "Screenshot.png", "size": 141909, "url": "http:\/\/uploads.hipchat.com\/xxx\/Screenshot.png" }, "message": "This is a file upload" }, { "date": "2010-11-19T16:13:40-0800", "from": { "name": "Deploy Bot", "user_id": "api" }, "message": "This message is sent via the API so the user_id is 'api'." } ] }hipchat-1.6.0/spec/hipchat_api_v2_spec.rb0000644000004100000410000005512313312114126020337 0ustar www-datawww-datarequire File.expand_path(File.dirname(__FILE__) + '/spec_helper') require'tempfile' describe "HipChat (API V2)" do subject { HipChat::Client.new("blah", :api_version => @api_version) } let(:room) { subject["Hipchat"] } let(:user) { subject.user "12345678" } describe "#scopes" do include_context "HipChatV2" let(:token_room) { nil } before { mock_successful_scopes room: token_room } context 'with a global API token' do context 'room parameter given' do it 'returns an array of global scopes' do expect(subject.scopes(room: room)) .to match_array(['view_room', 'send_notification']) end end context 'no room parameter given' do it 'returns an array of global scopes' do expect(subject.scopes) .to match_array(['view_room', 'send_notification']) end end end context 'with a room API token' do let(:token_room) { room } context 'room parameter given' do context 'room parameter matches API token room' do it 'returns an array of global scopes' do expect(subject.scopes(room: room)) .to match_array(['view_room', 'send_notification']) end end context 'room parameter does not match API token room' do let(:token_room) { double(room_id: 'Not-Hipchat') } it 'returns nil' do expect(subject.scopes(room: room)).to eq nil end end end context 'no room parameter given' do it 'returns nil' do expect(subject.scopes).to eq nil end end end it "fails if we get an unknown response code" do allow(subject.class) .to receive(:get).with(anything, anything) .and_return(OpenStruct.new(:code => 403)) expect { subject.scopes }.to raise_error(HipChat::Unauthorized) end end describe "#history" do include_context "HipChatV2" it "is successful without custom options" do mock_successful_history() expect(room.history()).to be_truthy end it "is successful with custom options" do mock_successful_history(:timezone => 'America/Los_Angeles', :date => '2010-11-19', :'max-results' => 10, :'start-index' => 10, :'end-date' => '2010-11-19') expect(room.history(:timezone => 'America/Los_Angeles', :date => '2010-11-19', :'max-results' => 10, :'start-index' => 10, :'end-date' => '2010-11-19')).to be_truthy end it "is successful from fetched room" do mock_successful_rooms mock_successful_history expect(subject.rooms).to be_truthy expect(subject.rooms.first.history).to be_truthy end it "fails when the room doesn't exist" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect { room.history }.to raise_error(HipChat::UnknownRoom) end it "fails when we're not allowed to do so" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect { room.history }.to raise_error(HipChat::Unauthorized) end it "fails if we get an unknown response code" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect { room.history }.to raise_error(HipChat::Unauthorized) end end describe "#statistics" do include_context "HipChatV2" it "is successful without custom options" do mock_successful_statistics expect(room.statistics()).to be_truthy end it "is successful from fetched room" do mock_successful_rooms mock_successful_statistics expect(subject.rooms).to be_truthy expect(subject.rooms.first.statistics).to be_truthy end it "fails when the room doesn't exist" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect { room.statistics }.to raise_error(HipChat::UnknownRoom) end it "fails when we're not allowed to do so" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect { room.statistics }.to raise_error(HipChat::Unauthorized) end it "fails if we get an unknown response code" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect { room.statistics }.to raise_error(HipChat::Unauthorized) end end describe "#topic" do include_context "HipChatV2" it "is successful without custom options" do mock_successful_topic_change("Nice topic") expect(room.topic("Nice topic")).to be_truthy end it "is successful with a custom from" do mock_successful_topic_change("Nice topic", :from => "Me") expect(room.topic("Nice topic", :from => "Me")).to be_truthy end it "fails when the room doesn't exist" do allow(room.class).to receive(:put).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect { room.topic "" }.to raise_error(HipChat::UnknownRoom) end it "fails when we're not allowed to do so" do allow(room.class).to receive(:put).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect { room.topic "" }.to raise_error(HipChat::Unauthorized) end it "fails if we get an unknown response code" do allow(room.class).to receive(:put).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect { room.topic "" }.to raise_error(HipChat::Unauthorized) end end describe "#send_message" do include_context "HipChatV2" it "successfully without custom options" do mock_successful_send_message 'Hello world' expect(room.send_message("Hello world")).to be_truthy end it "but fails when the room doesn't exist" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect { room.send_message "" }.to raise_error(HipChat::UnknownRoom) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect { room.send_message "" }.to raise_error(HipChat::Unauthorized) end it "but fails if we get an unknown response code" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect { room.send_message "" }.to raise_error(HipChat::Unauthorized) end end describe "#send" do include_context "HipChatV2" it "successfully without custom options" do mock_successful_send 'Dude', 'Hello world' expect(room.send("Dude", "Hello world")).to be_truthy end it "successfully with notifications on as option" do mock_successful_send 'Dude', 'Hello world', :notify => true expect(room.send("Dude", "Hello world", :notify => true)).to be_truthy end it "successfully with custom color" do mock_successful_send 'Dude', 'Hello world', :color => 'red' expect(room.send("Dude", "Hello world", :color => 'red')).to be_truthy end it "successfully creates a card in the room" do card = { :style => 'application', :title => 'My Awesome Card', :id => 12345 } mock_successful_send_card 'Dude', 'Hello world', card expect(room.send("Dude", "Hello world", :card => card)).to be_truthy end it "successfully with text message_format" do mock_successful_send 'Dude', 'Hello world', :message_format => 'text' expect(room.send("Dude", "Hello world", :message_format => 'text')).to be_truthy end it "but fails when the room doesn't exist" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect { room.send "", "" }.to raise_error(HipChat::UnknownRoom) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect { room.send "", "" }.to raise_error(HipChat::Unauthorized) end it "but fails if the username is more than 15 chars" do expect { room.send "a very long username here", "a message" }.to raise_error(HipChat::UsernameTooLong) end it "but fails if we get an unknown response code" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect { room.send "", "" }.to raise_error(HipChat::Unauthorized) end end describe '#reply' do include_context 'HipChatV2' let(:parent_id) { '100000' } let(:message) { 'Hello world' } it 'successfully' do mock_successful_reply parent_id, message expect(room.reply(parent_id, message)) end it "but fails when the parent_id doesn't exist" do allow(room.class).to receive(:post).and_return(OpenStruct.new(:code => 404)) expect { room.reply parent_id, message }.to raise_error(HipChat::UnknownRoom) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:post).and_return(OpenStruct.new(:code => 401)) expect { room.reply parent_id, message }.to raise_error(HipChat::Unauthorized) end it 'but fails if we get an unknown response code' do allow(room.class).to receive(:post).and_return(OpenStruct.new(:code => 403)) expect { room.reply parent_id, message }.to raise_error(HipChat::Unauthorized) end end describe '#share_link' do let(:link) { "http://i.imgur.com/cZ6GDFY.jpg" } include_context "HipChatV2" it "successfully" do mock_successful_link_share 'Dude', 'Sloth love Chunk!', link expect(room.share_link("Dude", "Sloth love Chunk!", link)).to be_truthy end it "but fails when the room doesn't exist" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect(lambda { room.share_link "", "", link }).to raise_error(HipChat::UnknownRoom) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect(lambda { room.share_link "", "", link }).to raise_error(HipChat::Unauthorized) end it "but fails if the username is more than 15 chars" do expect(lambda { room.share_link "a very long username here", "a message", link }).to raise_error(HipChat::UsernameTooLong) end it "but fails if we get an unknown response code" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect(lambda { room.share_link "", "", link }).to raise_error(HipChat::Unauthorized) end end describe "#send_file" do let(:file) do Tempfile.new('foo').tap do |f| f.write("the content") f.rewind end end after { file.unlink } include_context "HipChatV2" it "successfully" do mock_successful_file_send 'Dude', 'Hello world', file expect(room.send_file("Dude", "Hello world", file)).to be_truthy end it "but fails when the room doesn't exist" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect(lambda { room.send_file "", "", file }).to raise_error(HipChat::UnknownRoom) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect(lambda { room.send_file "", "", file }).to raise_error(HipChat::Unauthorized) end it "but fails if the username is more than 15 chars" do expect(lambda { room.send_file "a very long username here", "a message", file }).to raise_error(HipChat::UsernameTooLong) end it "but fails if we get an unknown response code" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect(lambda { room.send_file "", "", file }).to raise_error(HipChat::Unauthorized) end end describe "#create" do include_context "HipChatV2" it "successfully with room name" do mock_successful_room_creation("A Room") expect(subject.create_room("A Room")).to be_truthy end it "successfully with custom parameters" do mock_successful_room_creation("A Room", {:owner_user_id => "123456", :privacy => "private", :guest_access => true}) expect(subject.create_room("A Room", {:owner_user_id => "123456", :privacy => "private", :guest_access =>true})).to be_truthy end it "but fail is name is longer then 50 char" do expect { subject.create_room("A Room that is too long that I should fail right now") }. to raise_error(HipChat::RoomNameTooLong) end end describe "#create_user" do include_context "HipChatV2" it "successfully with user name" do mock_successful_user_creation("A User", "email@example.com") expect(subject.create_user("A User", "email@example.com")).to be_truthy end it "successfully with custom parameters" do mock_successful_user_creation("A User", "email@example.com", {:title => "Super user", :password => "password", :is_group_admin => true}) expect(subject.create_user("A User", "email@example.com", {:title => "Super user", :password => "password", :is_group_admin =>true})).to be_truthy end it "but fail is name is longer then 50 char" do expect { subject.create_user("A User that is too long that I should fail right now", "email@example.com") }. to raise_error(HipChat::UsernameTooLong) end end describe "#user_update" do include_context "HipChatV2" let(:user_update) { { :name => "Foo Bar", :presence => { status: "Away", show: "away" }, :mention_name => "foo", :timezone => "GMT", :email => "foo@bar.org", :title => "mister", :is_group_admin => 0, :roles => [] } } it "successfull" do mock_successful_user_update(user_update) user_update.delete(:presence) .each { |key, value| user_update[key] = value } expect(user.update(user_update)) end end describe "#get_room" do include_context "HipChatV2" it "successfully" do mock_successful_get_room("Hipchat") expect(room.get_room).to be_truthy end end describe "#update_room" do include_context "HipChatV2" let(:room_info) { { "name" => "hipchat", "topic" => "hipchat topic", "privacy" => "public", "is_archived" => false, "is_guest_accessible" => false, "owner" => { "id" => "12345" } } } it "successfully" do mock_successful_update_room("Hipchat", room_info) expect(room.update_room(room_info)).to be_truthy end end describe "#delete_room" do include_context "HipChatV2" it "successfully" do mock_successful_delete_room("Hipchat",) expect(room.delete_room).to be_truthy end it "missing room" do mock_delete_missing_room("Hipchat") expect do room.delete_room end.to raise_exception(HipChat::UnknownRoom) end end describe "#invite" do include_context "HipChatV2" it "successfully with user_id" do mock_successful_invite() expect(room.invite("1234")).to be_truthy end it "successfully with custom parameters" do mock_successful_invite({:user_id => "321", :reason => "A great reason"}) expect(room.invite("321", "A great reason")).to be_truthy end end describe "#add_member" do include_context "HipChatV2" it "successfully with user_id" do mock_successful_add_member() expect(room.add_member("1234")).to be_truthy end it "successfully with custom parameters" do mock_successful_add_member({:user_id => "321", :room_roles => ["room_admin","room_member"]}) expect(room.add_member("321", ["room_admin","room_member"])).to be_truthy end end describe "#send user message" do include_context "HipChatV2" it "successfully with a standard message" do mock_successful_user_send 'Equal bytes for everyone' expect(user.send('Equal bytes for everyone')).to be_truthy end it "but fails when the user doesn't exist" do allow(user.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect { user.send "" }.to raise_error(HipChat::UnknownUser) end it "but fails when we're not allowed to do so" do allow(user.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect { user.send "" }.to raise_error(HipChat::Unauthorized) end end describe '#get_user_history' do include_context 'HipChatV2' it 'successfully returns history' do mock_successful_user_history expect(user.history).to be_truthy end it 'has allowed params' do expect(user.instance_variable_get(:@api).history_config[:allowed_params]).to eq([:'max-results', :timezone, :'not-before']) end end describe "#send_file user" do include_context "HipChatV2" let(:file) do Tempfile.new('foo').tap do |f| f.write("the content") f.rewind end end it "successfully with a standard file" do mock_successful_user_send_file 'Equal bytes for everyone', file expect(user.send_file('Equal bytes for everyone', file)).to be_truthy end it "but fails when the user doesn't exist" do allow(user.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect(lambda { user.send_file "", file }).to raise_error(HipChat::UnknownUser) end it "but fails when we're not allowed to do so" do allow(user.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect(lambda { user.send_file "", file }).to raise_error(HipChat::Unauthorized) end end describe '#create_webhook' do include_context "HipChatV2" it "successfully with a valid room, url and event" do mock_successful_create_webhook('Hipchat', 'https://example.org/hooks/awesome', 'room_enter') expect(room.create_webhook('https://example.org/hooks/awesome', 'room_enter')).to be_truthy end it "but fails when the room doesn't exist" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect(lambda { room.create_webhook('https://example.org/hooks/awesome', 'room_enter') }).to raise_error(HipChat::UnknownRoom) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect(lambda { room.create_webhook('https://example.org/hooks/awesome', 'room_enter') }).to raise_error(HipChat::Unauthorized) end it "but fails if the url is invalid" do expect(lambda { room.create_webhook('foo://bar.baz/', 'room_enter') }).to raise_error(HipChat::InvalidUrl) end it "but fails if the event is invalid" do expect(lambda { room.create_webhook('https://example.org/hooks/awesome', 'room_vandalize') }).to raise_error(HipChat::InvalidEvent) end it "but fails if we get an unknown response code" do allow(room.class).to receive(:post).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect(lambda { room.create_webhook('https://example.org/hooks/awesome', 'room_enter') }).to raise_error(HipChat::Unauthorized) end end describe '#delete_webhook' do include_context "HipChatV2" it "successfully deletes a webhook with a valid webhook id" do mock_successful_delete_webhook('Hipchat', 'my_awesome_webhook') expect(room.delete_webhook('my_awesome_webhook')).to be_truthy end it "but fails when the webhook doesn't exist" do allow(room.class).to receive(:delete).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect(lambda { room.delete_webhook('my_awesome_webhook') }).to raise_error(HipChat::UnknownWebhook) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:delete).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect(lambda { room.delete_webhook('my_awesome_webhook') }).to raise_error(HipChat::Unauthorized) end it "but fails if we get an unknown response code" do allow(room.class).to receive(:delete).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect(lambda { room.delete_webhook('my_awesome_webhook') }).to raise_error(HipChat::Unauthorized) end end describe '#get_all_webhooks' do include_context "HipChatV2" it "successfully lists webhooks with a valid room id" do mock_successful_get_all_webhooks('Hipchat') expect(room.get_all_webhooks).to be_truthy end it "but fails when the room doesn't exist" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect(lambda { room.get_all_webhooks }).to raise_error(HipChat::UnknownRoom) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect(lambda { room.get_all_webhooks }).to raise_error(HipChat::Unauthorized) end it "but fails if we get an unknown response code" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect(lambda { room.get_all_webhooks }).to raise_error(HipChat::Unauthorized) end end describe '#get_webhook' do include_context "HipChatV2" it "successfully gets webhook info with valid room and webhook ids" do mock_successful_get_webhook('Hipchat', '5678') expect(room.get_webhook('5678')).to be_truthy end it "but fails when the webhook doesn't exist" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 404)) expect(lambda { room.get_webhook('5678') }).to raise_error(HipChat::UnknownWebhook) end it "but fails when we're not allowed to do so" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 401)) expect(lambda { room.get_webhook('5678') }).to raise_error(HipChat::Unauthorized) end it "but fails if we get an unknown response code" do allow(room.class).to receive(:get).with(anything, anything).and_return(OpenStruct.new(:code => 403)) expect(lambda { room.get_webhook('5678') }).to raise_error(HipChat::Unauthorized) end end end hipchat-1.6.0/spec/spec_helper.rb0000644000004100000410000000055313312114126016733 0ustar www-datawww-data$LOAD_PATH.unshift(File.dirname(__FILE__)) $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) require 'hipchat' require 'rspec' require 'json' require 'webmock/rspec' begin require 'coveralls' Coveralls.wear! rescue LoadError warn 'warning: coveralls gem not found; skipping coverage' end Dir["./spec/support/**/*.rb"].each {|f| require f}hipchat-1.6.0/spec/support/0000755000004100000410000000000013312114126015626 5ustar www-datawww-datahipchat-1.6.0/spec/support/shared_contexts_for_hipchat.rb0000644000004100000410000005716313312114126023732 0ustar www-datawww-dataHISTORY_JSON_PATH = File.expand_path(File.dirname(__FILE__) + '/../example/history.json') shared_context "HipChatV1" do before { @api_version = 'v1'} # Helper for mocking room message post requests def mock_successful_send(from, message, options={}) options = {:color => 'yellow', :notify => 0, :message_format => 'html'}.merge(options) stub_request(:post, "https://api.hipchat.com/v1/rooms/message").with( :query => {:auth_token => "blah"}, :body => {:room_id => "Hipchat", :from => "Dude", :message => "Hello world", :message_format => options[:message_format], :color => options[:color], :notify => "#{options[:notify]}"}, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'}).to_return(:status => 200, :body => "", :headers => {}) end def mock_successful_topic_change(topic, options={}) options = {:from => 'API'}.merge(options) stub_request(:post, "https://api.hipchat.com/v1/rooms/topic").with( :query => {:auth_token => "blah"}, :body => {:room_id => "Hipchat", :from => options[:from], :topic => "Nice topic" }, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'}).to_return(:status => 200, :body => "", :headers => {}) end def mock_successful_rooms stub_request(:get, "https://api.hipchat.com/v1/rooms/list").with( :query => {:auth_token => "blah"}, :body => "", :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'}).to_return( :status => 200, :body => '{"rooms":[{"room_id": "Hipchat", "links": {"self": "https://api.hipchat.com/v2/room/12345"}}]}', :headers => {}) end def mock_successful_history(options={}) options = { :date => 'recent', :timezone => 'UTC', :format => 'JSON', :'max-results' => 100, :'start-index' => 0 }.merge(options) canned_response = File.new(HISTORY_JSON_PATH) stub_request(:get, "https://api.hipchat.com/v1/rooms/history").with(:query => {:auth_token => "blah", :room_id => "Hipchat", :date => options[:date], :timezone => options[:timezone], :'max-results' => options[:'max-results'], :'start-index' => options[:'start-index'], :'end-date' => options[:'end-date'], :format => options[:format]}.reject!{|k,v| v.nil?}).to_return(canned_response) end def mock_successful_room_creation(name, options={}) options = {:name => "A Room"}.merge(options) stub_request(:post, "https://api.hipchat.com/v1/rooms/create").with( :query => {:auth_token => "blah"}, :body => { :name => name }.merge(options), :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'}).to_return( :status => 200, :body => '{"room": {"room_id": "1234", "name" : "A Room"}}', :headers => {}) end def mock_successful_user_creation(name, email, options={}) stub_request(:post, "https://api.hipchat.com/v1/users/create").with( :query => {:auth_token => "blah"}, :body => { :name => "A User", :email => "email@example.com" }.merge(options), :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'}).to_return( :status => 200, :body => '{"user": {"user_id": "1234", "A User" : "A User", "email" : "email@example.com"}}', :headers => {}) end def mock_successful_delete_room(room_id="1234") stub_request(:post, "https://api.hipchat.com/v1/rooms/delete").with( :query => {:auth_token => "blah", :room_id => room_id}, :headers => {"Accept" => "application/json", "Content-Type" => "application/x-www-form-urlencoded"}).to_return( :status => 204, :body => "", :headers => {}) end def mock_delete_missing_room(room_id="1234") stub_request(:post, "https://api.hipchat.com/v1/rooms/delete").with( :query => {:auth_token => "blah", :room_id => room_id}, :headers => {"Accept" => "application/json", "Content-Type" => "application/x-www-form-urlencoded"}).to_return( :status => 404, :body => "", :headers => {}) end end shared_context "HipChatV2" do before { @api_version = 'v2'} def mock_successful_send_message(message) stub_request(:post, "https://api.hipchat.com/v2/room/Hipchat/message").with( :query => {:auth_token => "blah"}, :body => {:room_id => "Hipchat", :message => "Hello world"}.to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 200, :body => "", :headers => {}) end # Helper for mocking room message post requests def mock_successful_send(from, message, options={}) options = {:color => 'yellow', :notify => false, :message_format => 'html'}.merge(options) stub_request(:post, "https://api.hipchat.com/v2/room/Hipchat/notification").with( :query => {:auth_token => "blah"}, :body => {:room_id => "Hipchat", :from => "Dude", :message => "Hello world", :message_format => options[:message_format], :color => options[:color], :notify => options[:notify]}.to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 200, :body => "", :headers => {}) end def mock_successful_reply(parent_message_id, message) stub_request(:post, 'https://api.hipchat.com/v2/room/Hipchat/reply?auth_token=blah') .with(query: { auth_token: 'blah' }, body: { parent_message_id: parent_message_id, message: message }, headers: { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }) .to_return(status: 200, body: '', headers: {}) end def mock_successful_link_share(from, message, link) stub_request(:post, "https://api.hipchat.com/v2/room/Hipchat/share/link").with( :query => {:auth_token => "blah"}, :body => {:room_id => "Hipchat", :from => "Dude", :message => message, :link => link}.to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 200, :body => "", :headers => {}) end def mock_successful_file_send(from, message, file) stub_request(:post, "https://api.hipchat.com/v2/room/Hipchat/share/file").with( :query => {:auth_token => "blah"}, :body => "--sendfileboundary\nContent-Type: application/json; charset=UTF-8\nContent-Disposition: attachment; name=\"metadata\"\n\n{\"room_id\":\"Hipchat\",\"from\":\"Dude\",\"message\":\"Hello world\"}\n--sendfileboundary\nContent-Type: ; charset=UTF-8\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment; name=\"file\"; filename=\"#{File.basename(file.path)}\"\n\ndGhlIGNvbnRlbnQ=\n\n--sendfileboundary--", :headers => {'Accept' => 'application/json', 'Content-Type' => 'multipart/related; boundary=sendfileboundary'}).to_return(:status => 200, :body => "", :headers => {}) end def mock_successful_send_card(from, message, card) options = {:color => 'yellow', :notify => false, :message_format => 'html'} stub_request(:post, "https://api.hipchat.com/v2/room/Hipchat/notification").with( :query => {:auth_token => "blah"}, :body => {:room_id => "Hipchat", :from => "Dude", :message => "Hello world", :message_format => options[:message_format], :color => options[:color], :card => card, :notify => options[:notify]}.to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 200, :body => "", :headers => {}) end def mock_successful_topic_change(topic, options={}) options = {:from => 'API'}.merge(options) stub_request(:put, "https://api.hipchat.com/v2/room/Hipchat/topic").with( :query => {:auth_token => "blah"}, :body => {:room_id => "Hipchat", :from => options[:from], :topic => "Nice topic" }.to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 200, :body => "", :headers => {}) end def mock_successful_rooms stub_request(:get, "https://api.hipchat.com/v2/room").with( :query => {:auth_token => "blah"}, :body => "", :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return( :status => 200, :body => '{"items":[{"id": "Hipchat", "links": {"self": "https://api.hipchat.com/v2/room/12345"}}]}', :headers => {}) end def mock_successful_scopes(room: nil) token_room = room ? { id: room.room_id, name: 'example' } : nil stub_request(:get, 'https://api.hipchat.com/v2/oauth/token/blah').with( :query => { :auth_token => 'blah' }, :body => '', :headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' } ).to_return( :status => 200, :body => { client: { allowed_scopes: [:view_room, :send_notification], name: 'All perms', room: token_room }, scopes: [:view_room, :send_notification] }.to_json, :headers => {} ) end def mock_successful_history(options={}) options = { :date => 'recent', :timezone => 'UTC', :format => 'JSON', :'max-results' => 100, :'start-index' => 0 }.merge(options) canned_response = File.new(HISTORY_JSON_PATH) stub_request(:get, "https://api.hipchat.com/v2/room/Hipchat/history").with(:query => {:auth_token => "blah", :room_id => "Hipchat", :date => options[:date], :timezone => options[:timezone], :'max-results' => options[:'max-results'], :'start-index' => options[:'start-index'], :'end-date' => options[:'end-date'], :format => options[:format]}.reject!{|k,v| v.nil?}).to_return(canned_response) end def mock_successful_statistics(options={}) stub_request(:get, "https://api.hipchat.com/v2/room/Hipchat/statistics").with(:query => {:auth_token => "blah", :room_id => "Hipchat", :date => options[:date], :timezone => options[:timezone], :format => options[:format]}.reject!{|k,v| v.nil?}).to_return( :status => 200, :body => '{"last_active": "2014-09-02T21:33:54+00:00", "links": {"self": "https://api.hipchat.com/v2/room/12345/statistics"}, "messages_sent": 10}', :headers => {}) end def mock_successful_room_creation(name, options={}) stub_request(:post, "https://api.hipchat.com/v2/room").with( :query => {:auth_token => "blah"}, :body => { :name => name }.merge(options).to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return( :status => 201, :body => '{"id": "12345", "links": {"self": "https://api.hipchat.com/v2/room/12345"}}', :headers => {}) end def mock_successful_user_creation(name, email, options={}) stub_request(:post, "https://api.hipchat.com/v2/user").with( :query => {:auth_token => "blah"}, :body => { :name => name, :email => email }.merge(options).to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return( :status => 201, :body => '{"id": "12345", "links": {"self": "https://api.hipchat.com/v2/user/12345"}}', :headers => {}) end def mock_successful_get_room(room_id="1234") stub_request(:get, "https://api.hipchat.com/v2/room/#{room_id}").with( :query => {:auth_token => "blah"}, :body => "", :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 200, :body => "{\"id\":\"#{room_id}\"}", :headers => {}) end def mock_successful_update_room(room_id="1234", options={}) stub_request(:put, "https://api.hipchat.com/v2/room/#{room_id}").with( :query => {:auth_token => "blah"}, :body => { :name => "hipchat", :topic => "hipchat topic", :privacy => "public", :is_archived => false, :is_guest_accessible => false, :owner => { :id => "12345" } }.to_json, :headers => {"Accept" => "application/json", "Content-Type" => "application/json"}).to_return( :status => 204, :body => "", :headers => {}) end def mock_successful_delete_room(room_id="1234") stub_request(:delete, "https://api.hipchat.com/v2/room/#{room_id}").with( :query => {:auth_token => "blah"}, :headers => {"Accept" => "application/json", "Content-Type" => "application/json"}).to_return( :status => 204, :body => "", :headers => {}) end def mock_delete_missing_room(room_id="1234") stub_request(:delete, "https://api.hipchat.com/v2/room/#{room_id}").with( :query => {:auth_token => "blah"}, :headers => {"Accept" => "application/json", "Content-Type" => "application/json"}).to_return( :status => 404, :body => "", :headers => {}) end def mock_successful_invite(options={}) options = {:user_id => "1234"}.merge(options) stub_request(:post, "https://api.hipchat.com/v2/room/Hipchat/invite/#{options[:user_id]}").with( :query => {:auth_token => "blah"}, :body => { :reason => options[:reason]||"" }.to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return( :status => 204, :body => "", :headers => {}) end def mock_successful_add_member(options={}) options = {:user_id => "1234"}.merge(options) stub_request(:put, "https://api.hipchat.com/v2/room/Hipchat/member/#{options[:user_id]}").with( :query => {:auth_token => "blah"}, :body => { :room_roles => options[:room_roles] || ["room_member"] }.to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return( :status => 204, :body => "", :headers => {}) end def mock_successful_user_send(message) stub_request(:post, "https://api.hipchat.com/v2/user/12345678/message").with( :query => {:auth_token => "blah"}, :body => {:message => "Equal bytes for everyone", :message_format => "text", :notify => false}, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 200, :body => "", :headers => {}) end def mock_successful_user_history() canned_response = File.new(HISTORY_JSON_PATH) url = 'https://api.hipchat.com/v2/user/12345678/history/latest' stub_request(:get, url).with(:query => { :auth_token => "blah" }, :headers => { 'Accept' => 'application/json', 'Content-Type' => 'application/json' }).to_return(canned_response) end def mock_successful_user_send_file(message, file) stub_request(:post, "https://api.hipchat.com/v2/user/12345678/share/file").with( :query => {:auth_token => "blah"}, :body => "--sendfileboundary\nContent-Type: application/json; charset=UTF-8\nContent-Disposition: attachment; name=\"metadata\"\n\n{\"message\":\"Equal bytes for everyone\"}\n--sendfileboundary\nContent-Type: ; charset=UTF-8\nContent-Transfer-Encoding: base64\nContent-Disposition: attachment; name=\"file\"; filename=\"#{File.basename(file)}\"\n\ndGhlIGNvbnRlbnQ=\n\n--sendfileboundary--", :headers => {'Accept' => 'application/json', 'Content-Type' => 'multipart/related; boundary=sendfileboundary'}).to_return(:status => 200, :body => "", :headers => {}) end def mock_successful_user_update(options) stub_request(:put, "https://api.hipchat.com/v2/user/12345678").with( :query => {:auth_token => "blah"}, :body => options.to_json, :headers => {"Accept" => "application/json", "Content-Type" => "application/json"}).to_return( :status => 204, :body => "", :headers => {}) end def mock_successful_create_webhook(room_id, url, event, options = {}) options = {:pattern => '', :name => ''}.merge(options) stub_request(:post, "https://api.hipchat.com/v2/room/#{room_id}/webhook").with( :query => {:auth_token => "blah"}, :body => {:url => url, :pattern => options[:pattern], :event => event, :name => options[:name]}.to_json, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 201, :body => {:id => '1234', :links => {:self => "https://api.hipchat.com/v2/room/#{room_id}/webhook/1234"}}.to_json, :headers => {}) end def mock_successful_delete_webhook(room_id, webhook_id) stub_request(:delete, "https://api.hipchat.com/v2/room/#{room_id}/webhook/#{webhook_id}").with( :query => {:auth_token => "blah"}, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 204, :headers => {}) end def mock_successful_get_all_webhooks(room_id, options = {}) options = {:'start-index' => 0, :'max-results' => 100}.merge(options) stub_request(:get, "https://api.hipchat.com/v2/room/#{room_id}/webhook").with( :query => {:auth_token => "blah", :'start-index' => options[:'start-index'], :'max-results' => options[:'max-results']}, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 200, :body => {:items => [], :startIndex => 0, :maxResults => 100, :links => {:self => "https://api.hipchat.com/v2/room/#{room_id}/webhook"}}.to_json, :headers => {}) end def mock_successful_get_webhook(room_id, webhook_id) stub_request(:get, "https://api.hipchat.com/v2/room/#{room_id}/webhook/#{webhook_id}").with( :query => {:auth_token => "blah"}, :headers => {'Accept' => 'application/json', 'Content-Type' => 'application/json'}).to_return(:status => 200, :body => {:room => nil, :links => {:self => "https://api.hipchat.com/v2/room/#{room_id}/webhook/#{webhook_id}"}, :creator => nil, :url => 'http://example.org/webhook', :created => '2014-09-02T21:33:54+00:00', :event => 'room_deleted'}.to_json, :headers => {}) end end hipchat-1.6.0/.gitignore0000644000004100000410000000046413312114126015154 0ustar www-datawww-data## MAC OS .DS_Store ## TEXTMATE *.tmproj tmtags ## EMACS *~ \#* .\#* ## VIM *.swp ## IntelliJ *.iml .idea ## PROJECT::GENERAL coverage rdoc pkg *.gem *.rbc .bundle .config .yardoc /Gemfile.lock InstalledFiles _yardoc doc/ lib/bundler/man spec/reports test/tmp test/version_tmp tmp ## PROJECT::SPECIFIC hipchat-1.6.0/LICENSE0000644000004100000410000000203513312114126014165 0ustar www-datawww-dataCopyright (c) 2012 Atlassian Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. hipchat-1.6.0/.document0000644000004100000410000000007413312114126015000 0ustar www-datawww-dataREADME.rdoc lib/**/*.rb bin/* features/**/*.feature LICENSE hipchat-1.6.0/Rakefile0000644000004100000410000000062413312114126014627 0ustar www-datawww-datarequire "bundler/gem_tasks" require 'rspec/core/rake_task' RSpec::Core::RakeTask.new do |t| t.pattern = 'spec/**/*_spec.rb' t.rspec_opts = '-c -fd' end task :default => :spec require 'rdoc/task' Rake::RDocTask.new do |rdoc| version = HipChat::VERSION rdoc.rdoc_dir = 'rdoc' rdoc.title = "hipchat #{version}" rdoc.rdoc_files.include('README*') rdoc.rdoc_files.include('lib/**/*.rb') end hipchat-1.6.0/lib/0000755000004100000410000000000013312114126013726 5ustar www-datawww-datahipchat-1.6.0/lib/hipchat.rb0000644000004100000410000000041413312114126015672 0ustar www-datawww-datarequire 'hipchat/railtie' if defined?(Rails::Railtie) require 'hipchat/version' module HipChat require 'hipchat/api_version' require 'hipchat/errors' require 'hipchat/file_helper' require 'hipchat/room' require 'hipchat/client' require 'hipchat/user' end hipchat-1.6.0/lib/hipchat/0000755000004100000410000000000013312114126015346 5ustar www-datawww-datahipchat-1.6.0/lib/hipchat/file_helper.rb0000644000004100000410000000221713312114126020153 0ustar www-datawww-datarequire 'mimemagic' module HipChat module FileHelper BOUNDARY = "sendfileboundary" private # # Builds a multipart file body for the api. # # message - a message to attach # file - a File instance def file_body(message, file) file_name = File.basename(file.path) mime_type = MimeMagic.by_path(file_name) file_content = Base64.encode64(file.read) body = ["--#{BOUNDARY}"] body << 'Content-Type: application/json; charset=UTF-8' body << 'Content-Disposition: attachment; name="metadata"' body << '' body << message body << "--#{BOUNDARY}" body << "Content-Type: #{mime_type}; charset=UTF-8" body << 'Content-Transfer-Encoding: base64' body << %{Content-Disposition: attachment; name="file"; filename="#{file_name}"} body << '' body << file_content body << "--#{BOUNDARY}--" body.join("\n") end # # Appends headers require for the multipart body. # # headers - a base headers hash def file_body_headers(headers) headers.merge('Content-Type' => "multipart/related; boundary=#{BOUNDARY}") end end end hipchat-1.6.0/lib/hipchat/version.rb0000644000004100000410000000004713312114126017361 0ustar www-datawww-datamodule HipChat VERSION = '1.6.0' end hipchat-1.6.0/lib/hipchat/api_version.rb0000644000004100000410000002231013312114126020207 0ustar www-datawww-datarequire 'uri' module HipChat class ApiVersion def bool_val(opt) if version.eql?('v1') opt ? 1 : 0 else opt end end class Client < ApiVersion def initialize(options = {}) # puts options.inspect @version = options[:api_version] if @version.eql?('v1') @base_uri = "#{options[:server_url]}/v1" @headers = {'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'} elsif @version.eql?('v2') @base_uri = "#{options[:server_url]}/v2" @headers = {'Accept' => 'application/json', 'Content-Type' => 'application/json'} else raise InvalidApiVersion, 'Couldn\'t recognize API version' end end attr_reader :version, :base_uri, :headers def rooms_config { 'v1' => { :url => '/rooms/list', :data_key => 'rooms' }, 'v2' => { :url => '/room', :data_key => 'items' } }[version] end def create_room_config { 'v1' => { :url => '/rooms/create', :body_format => :to_hash }, 'v2' => { :url => '/room', :body_format => :to_json } }[version] end def create_user_config { 'v1' => { :url => '/users/create', :body_format => :to_hash }, 'v2' => { :url => '/user', :body_format => :to_json } }[version] end def users_config { 'v1' => { :url => '/users/list', :data_key => 'users' }, 'v2' => { :url => '/user', :data_key => 'items' } }[version] end def scopes_config raise InvalidApiVersion, 'This functionality is not supported in API v1' unless version.eql?('v2') { 'v2' => { :url => URI::escape("/oauth/token") } }[version] end end class Room < ApiVersion def initialize(options = {}) @version = options[:api_version] options[:room_id] ||= options[get_id_attribute] @room_id = options[:room_id] if @version.eql?('v1') @base_uri = "#{options[:server_url]}/v1/rooms" @headers = {'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'} else @base_uri = "#{options[:server_url]}/v2/room" @headers = {'Accept' => 'application/json', 'Content-Type' => 'application/json'} end end attr_reader :version, :base_uri, :room_id, :headers def get_id_attribute version.eql?('v1') ? 'room_id' : 'id' end def get_room_config { 'v1' => { :url => URI::escape('/show'), :query_params => { :room_id => room_id } }, 'v2' => { :url => URI::escape("/#{room_id}"), :query_params => { } } }[version] end def update_room_config { 'v2' => { :url => URI::escape("/#{room_id}"), :method => :put, :body_format => :to_json } }[version] end def delete_room_config { 'v1' => { :url => URI::escape("/delete"), :method => :post, :query_params => { :room_id => room_id } }, 'v2' => { :url => URI::escape("/#{room_id}"), :method => :delete, :query_params => {} } }[version] end def invite_config { 'v2' => { :url => URI::escape("/#{room_id}/invite"), :body_format => :to_json } }[version] end def add_member_config { 'v2' => { :url => URI::escape("/#{room_id}/member"), :body_format => :to_json } }[version] end def send_message_config { 'v2' => { :url => URI::escape("/#{room_id}/message"), :body_format => :to_json } }[version] end def send_config { 'v1' => { :url => "/message", :body_format => :to_hash }, 'v2' => { :url => URI::escape("/#{room_id}/notification"), :body_format => :to_json } }[version] end def reply_config { 'v2' => { :url => URI::escape("/#{room_id}/reply"), :method => :post, :query_params => { }, :body_format => :to_json } }[version] end def send_file_config { 'v2' => { :url => URI::escape("/#{room_id}/share/file"), :body_format => :to_json } }[version] end def share_link_config { 'v2' => { :url => URI::escape("/#{room_id}/share/link"), :body_format => :to_json } }[version] end def topic_config { 'v1' => { :url => '/topic', :method => :post, :body_format => :to_hash }, 'v2' => { :url => URI::escape("/#{room_id}/topic"), :method => :put, :body_format => :to_json } }[version] end def history_config { 'v1' => { :url => '/history' }, 'v2' => { :url => URI::escape("/#{room_id}/history") } }[version] end def statistics_config { 'v2' => { :url => URI::escape("/#{room_id}/statistics") } }[version] end def webhook_config raise InvalidApiVersion, 'This functionality is not supported in API v1' unless version.eql?('v2') { 'v2' => { :url => URI::escape("/#{room_id}/webhook") } }[version] end end class User def initialize(options) @version = options[:api_version] options[:user_id] ||= options[get_id_attribute] @user_id = options[:user_id] if @version.eql?('v1') @base_uri = "#{options[:server_url]}/v1/users" @headers = {'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'} else @base_uri = "#{options[:server_url]}/v2/user" @headers = {'Accept' => 'application/json', 'Content-Type' => 'application/json'} end end attr_reader :version, :base_uri, :user_id, :headers def get_id_attribute version.eql?('v1') ? 'user_id' : 'id' end def send_config raise InvalidApiVersion, 'This functionality is not supported in API v1' unless version.eql?('v2') { :url => URI::escape("/#{user_id}/message"), :body_format => :to_json } end def send_file_config { :url => URI::escape("/#{user_id}/share/file"), :body_format => :to_json } end def view_config { 'v1' => { :url => URI::escape('/show'), :body_format => :to_json, :query_params => { :user_id => user_id } }, 'v2' => { :url => URI::escape("/#{user_id}"), :body_format => :to_json, :query_params => {} } }[version] end def user_joined_rooms_config raise InvalidApiVersion, 'This functionality is not supported in API v1' unless version.eql?('v2') { 'v2' => { :url => URI::escape("/#{user_id}/preference/auto-join"), :body_format => :to_json, :query_params => {} } }[version] end #Same signature as view_config but separating code to keep any future changes safe def user_update_config { 'v1' => { :url => URI::escape('/show'), :body_format => :to_json, :query_params => { :user_id => user_id } }, 'v2' => { :url => URI::escape("/#{user_id}"), :body_format => :to_json, :query_params => {} } }[version] end def delete_config { 'v1' => { :url => URI::escape('/delete'), :body_format => :to_json, :query_params => { :user_id => user_id } }, 'v2' => { :url => URI::escape("/#{user_id}"), :body_format => :to_json, :query_params => {} } }[version] end def history_config raise InvalidApiVersion, 'This functionality is not supported in API v1' unless version.eql?('v2') { :url => URI::escape("/#{user_id}/history/latest"), :body_format => :to_json, :allowed_params => [:'max-results', :timezone, :'not-before'] } end end end end hipchat-1.6.0/lib/hipchat/railtie.rb0000644000004100000410000000017113312114126017323 0ustar www-datawww-datamodule HipChat class Railtie < Rails::Railtie rake_tasks do require 'hipchat/rails3_tasks' end end end hipchat-1.6.0/lib/hipchat/user.rb0000644000004100000410000001425713312114126016662 0ustar www-datawww-datarequire 'httparty' require 'ostruct' module HipChat class User < OpenStruct include HTTParty include FileHelper format :json def initialize(token, params) @token = token @api = HipChat::ApiVersion::User.new(params) self.class.base_uri(@api.base_uri) super(params) end # # Send a private message to user. # def send(message, options = {}) message_format = options[:message_format] ? options[:message_format] : 'text' notify = options[:notify] ? options[:notify] : false response = self.class.post(@api.send_config[:url], :query => { :auth_token => @token }, :body => { :message => message, :message_format => message_format, :notify => notify }.send(@api.send_config[:body_format]), :headers => @api.headers ) ErrorHandler.response_code_to_exception_for :user, user_id, response true end # # Send a private file to user. # def send_file(message, file) response = self.class.post(@api.send_file_config[:url], :query => { :auth_token => @token }, :body => file_body({ :message => message }.send(@api.send_config[:body_format]), file), :headers => file_body_headers(@api.headers) ) ErrorHandler.response_code_to_exception_for :user, user_id, response true end # # Get a user's details. # def view response = self.class.get(@api.view_config[:url], :query => { :auth_token => @token }.merge(@api.view_config[:query_params]), :headers => @api.headers ) ErrorHandler.response_code_to_exception_for :user, user_id, response User.new(@token, response.merge(:api_version => @api.version, :server_url => server_url)) end # # Get private message history # def history(params = {}) params.select! { |key, _value| @api.history_config[:allowed_params].include? key } response = self.class.get(@api.history_config[:url], :query => { :auth_token => @token }.merge(params), :headers => @api.headers ) ErrorHandler.response_code_to_exception_for :user, user_id, response response.body end # # Get private message history # def delete(params = {}) case @api.version when 'v1' response = self.class.post(@api.delete_config[:url], :query => { :auth_token => @token }.merge(params), :headers => @api.headers ) when 'v2' response = self.class.delete(@api.delete_config[:url], :query => { :auth_token => @token }, :headers => @api.headers ) end ErrorHandler.response_code_to_exception_for :user, user_id, response true end # # User update. # API: https://www.hipchat.com/docs/apiv2/method/update_user # Request body # name - REQUIRED - User's full name. Valid length range: 1-50 # roles - The list of roles for the user. For example "owner", "administrator", "user", "delegated administrator" # title - User's title # status - string may be null # show - REQUIRED - string - the status to show for the user. Available options 'away', 'chat', 'dnd', 'xa' # mention_name - REQUIRED - User's @mention name without the @ # is_group_admin - Whether or not this user is an administrator # timezone - User's timezone. Must be a supported timezone. Defaults to 'UTC' # password - User's password. If not provided, the existing password is kept # email - REQUIRED - User's email def update(options = {}) name = options[:name] roles = options[:roles] ? options[:roles] : nil title = options[:title] ? options[:title] : nil status = options[:status] ? options[:status] : nil show = options[:show] ? options[:show] : nil mention_name = options[:mention_name] is_group_admin = options[:is_group_admin] ? options[:is_group_admin] : nil timezone = options[:timezone] ? options[:timezone] : 'UTC' password = options[:password] ? options[:password] : nil email = options[:email] #create body format body = { } response = self.class.put(@api.user_update_config[:url], :query => { :auth_token => @token }, :body => { :name => name, :presence => {:status=>status, :show=>show}, :mention_name => mention_name, :timezone => timezone, :email => email } .merge(title ? {:title =>title} : {}) .merge(password ? {:password => password} : {}) .merge(is_group_admin ? {:is_group_admin => is_group_admin} : {}) .merge(roles ? {:roles => roles} : {}) .send(@api.user_update_config[:body_format]), :headers => @api.headers ) ErrorHandler.response_code_to_exception_for :user, user_id, response end # # Getting all rooms details in which user is present # def rooms response = self.class.get(@api.user_joined_rooms_config[:url], :query => { :auth_token => @token }.merge(@api.user_joined_rooms_config[:query_params]), :headers => @api.headers ) ErrorHandler.response_code_to_exception_for :user, user_id, response User.new(@token, response.merge(:api_version => @api.version)) end end end hipchat-1.6.0/lib/hipchat/capistrano2.rb0000644000004100000410000001310213312114126020115 0ustar www-datawww-datarequire 'hipchat' Capistrano::Configuration.instance(:must_exist).load do set :hipchat_send_notification, false set :hipchat_with_migrations, '' namespace :hipchat do task :trigger_notification do set :hipchat_send_notification, true if !dry_run end task :configure_for_migrations do set :hipchat_with_migrations, ' (with migrations)' end task :notify_deploy_started do if hipchat_send_notification environment_string = env if self.respond_to?(:stage) environment_string = "#{stage} (#{env})" end on_rollback do send_options.merge!(:color => failed_message_color) send("#{human} cancelled deployment of #{deployment_name} to #{environment_string}.", send_options) end send("#{human} is deploying #{deployment_name} to #{environment_string}#{fetch(:hipchat_with_migrations, '')}.", send_options) end end task :notify_deploy_finished do if hipchat_send_notification send_options.merge!(:color => success_message_color) environment_string = env if self.respond_to?(:stage) environment_string = "#{stage} (#{env})" end if fetch(:hipchat_commit_log, false) logs = commit_logs unless logs.empty? send(logs.join(commit_log_line_separator), send_options) end end send("#{human} finished deploying #{deployment_name} to #{environment_string}#{fetch(:hipchat_with_migrations, '')}.", send_options) end end def send_options return @send_options if defined?(@send_options) @send_options = message_format ? {:message_format => message_format } : {} @send_options.merge!(:notify => message_notification) @send_options.merge!(:color => message_color) @send_options end def send(message, options) return unless enabled? hipchat_options = fetch(:hipchat_options, {}) set :hipchat_client, HipChat::Client.new(hipchat_token, hipchat_options) if fetch(:hipchat_client, nil).nil? if hipchat_room_name.is_a?(String) rooms = [hipchat_room_name] elsif hipchat_room_name.is_a?(Symbol) rooms = [hipchat_room_name.to_s] else rooms = hipchat_room_name end rooms.each { |room| begin hipchat_client[room].send(deploy_user, message, options) rescue => e puts e.message puts e.backtrace end } end def enabled? fetch(:hipchat_enabled, true) end def deployment_name if fetch(:branch, nil) name = "#{application}/#{branch}" name += " (revision #{real_revision[0..7]})" if real_revision name else application end end def message_color fetch(:hipchat_color, nil) end def success_message_color fetch(:hipchat_success_color, "green") end def failed_message_color fetch(:hipchat_failed_color, "red") end def message_notification fetch(:hipchat_announce, false) end def message_format fetch(:hipchat_message_format, "html") end def deploy_user fetch(:hipchat_deploy_user, "Deploy") end def human ENV['HIPCHAT_USER'] || fetch(:hipchat_human, if (u = %x{git config user.name}.strip) != "" u elsif (u = ENV['USER']) != "" u else "Someone" end) end def env fetch(:hipchat_env, fetch(:rack_env, fetch(:rails_env, "production"))) end def commit_log_line_separator message_format == "html" ? "
" : "\n" end end def commit_logs from = (previous_revision rescue nil) to = (latest_revision rescue nil) log_hashes = [] case scm.to_s when 'git' logs = run_locally(source.local.scm(:log, "--no-merges --pretty=format:'%H$$%at$$%an$$%s' #{from}..#{to}")) logs.split(/\n/).each do |log| ll = log.split(/\$\$/) log_hashes << {revision: ll[0], time: Time.at(ll[1].to_i), user: ll[2], message: ll[3]} end when 'svn' logs = run_locally(source.local.scm(:log, "--non-interactive -r #{from}:#{to}")) logs.scan(/^[-]+$\n\s*(?[^\|]+)\s+\|\s+(?[^\|]+)\s+\|\s+(?