diff --git a/spec/factories/channel.rb b/spec/factories/channel.rb
index e12e4776d..0d991ebf7 100644
--- a/spec/factories/channel.rb
+++ b/spec/factories/channel.rb
@@ -9,19 +9,23 @@ FactoryBot.define do
created_by_id 1
factory :twitter_channel do
+ transient do
+ custom_options { {} }
+ end
+
area 'Twitter::Account'
options do
{
adapter: 'twitter',
auth: {
- consumer_key: 'some',
- consumer_secret: 'some',
- oauth_token: 'key',
+ consumer_key: 'some',
+ consumer_secret: 'some',
+ oauth_token: 'key',
oauth_token_secret: 'secret',
},
user: {
- screen_name: 'system_login',
id: 'system_id',
+ screen_name: 'system_login',
},
sync: {
import_older_tweets: true,
@@ -29,21 +33,21 @@ FactoryBot.define do
search: [
{
term: 'zammad',
- group_id: Group.first.id,
+ group_id: Group.first.id
},
{
term: 'hash_tag1',
- group_id: Group.first.id,
- },
+ group_id: Group.first.id
+ }
],
mentions: {
- group_id: Group.first.id,
+ group_id: Group.first.id
},
direct_messages: {
- group_id: Group.first.id,
+ group_id: Group.first.id
}
}
- }
+ }.deep_merge(custom_options)
end
end
end
diff --git a/spec/requests/integration/twitter_webhook_spec.rb b/spec/requests/integration/twitter_webhook_spec.rb
index 783afd86c..e02cf7a7d 100644
--- a/spec/requests/integration/twitter_webhook_spec.rb
+++ b/spec/requests/integration/twitter_webhook_spec.rb
@@ -1,282 +1,412 @@
require 'rails_helper'
-RSpec.describe 'Integration Twitter Webhook', type: :request do
+RSpec.describe 'Twitter Webhook Integration', type: :request do
+ let!(:external_credential) { create(:twitter_credential, credentials: credentials) }
+ let(:credentials) { { consumer_key: 'CCC', consumer_secret: 'DDD' } }
- let(:agent_user) do
- create(:agent_user)
+ describe '#webhook_verify (for Twitter to confirm Zammad’s credentials)' do
+ context 'with only cached credentials' do
+ let!(:external_credential) { nil }
+ before { Cache.write('external_credential_twitter', credentials) }
+
+ it 'returns an HMAC signature for cached credentials plus params[:crc_token]' do
+ get '/api/v1/channels_twitter_webhook',
+ params: { crc_token: 'some_random', nonce: 'some_nonce' },
+ headers: { 'x-twitter-webhooks-signature' => 'something' },
+ as: :json
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to include('response_token' => 'sha256=VE19eUk6krbdSqWPdvH71xtFhApBAU81uPW3UT65vOs=')
+ end
+ end
+
+ context 'with only credentials stored in DB' do
+ it 'returns an HMAC signature for stored credentials plus params[:crc_token]' do
+ get '/api/v1/channels_twitter_webhook',
+ params: { crc_token: 'some_random', nonce: 'some_nonce' },
+ headers: { 'x-twitter-webhooks-signature' => 'something' },
+ as: :json
+
+ expect(response).to have_http_status(200)
+ expect(json_response).to include('response_token' => 'sha256=VE19eUk6krbdSqWPdvH71xtFhApBAU81uPW3UT65vOs=')
+ end
+ end
end
- before(:each) do
- @external_credential = ExternalCredential.create!(
- name: 'twitter',
- credentials: {
- consumer_key: 'CCC',
- consumer_secret: 'DDD',
- }
- )
- @channel = Channel.create!(
- group_id: nil,
- area: 'Twitter::Account',
- options: {
- adapter: 'twitter',
- user: {
- id: 123,
- screen_name: 'zammadhq',
- name: 'Zammad HQ',
- },
- auth: {
- external_credential_id: 1,
- oauth_token: 'AAA',
- oauth_token_secret: 'BBB',
- consumer_key: 'CCC',
- consumer_secret: 'DDD',
- },
- sync: {
- limit: 20,
- search: [{ term: '#zammad', group_id: Group.first.id.to_s }, { term: '#hello1234', group_id: Group.first.id.to_s }],
- mentions: { group_id: Group.first.id.to_s },
- direct_messages: { group_id: Group.first.id.to_s },
- track_retweets: false
+ describe '#webhook_incoming' do
+ let!(:channel) do
+ create(
+ :twitter_channel,
+ custom_options: {
+ auth: {
+ external_credential_id: external_credential.id,
+ oauth_token: 'AAA',
+ oauth_token_secret: 'BBB',
+ consumer_key: 'CCC',
+ consumer_secret: 'DDD',
+ },
+ user: {
+ id: 123,
+ name: 'Zammad HQ',
+ screen_name: 'zammadhq',
+ },
+ sync: {
+ limit: 20,
+ track_retweets: false,
+ search: [
+ {
+ term: '#zammad', group_id: Group.first.id.to_s
+ },
+ {
+ term: '#hello1234', group_id: Group.first.id.to_s
+ }
+ ],
+ }
}
- },
- active: true,
- updated_by_id: 1,
- created_by_id: 1,
- )
- end
-
- describe 'request verify' do
-
- it 'does at config check' do
- Cache.write('external_credential_twitter', @external_credential.credentials)
- @external_credential.destroy
- params = {
- crc_token: 'some_random',
- nonce: 'some_nonce',
- }
- get '/api/v1/channels_twitter_webhook', params: params, headers: { 'x-twitter-webhooks-signature' => 'something' }, as: :json
- expect(response).to have_http_status(200)
- expect(json_response['response_token']).to eq('sha256=VE19eUk6krbdSqWPdvH71xtFhApBAU81uPW3UT65vOs=')
+ )
end
- it 'does configured check' do
- Cache.delete('external_credential_twitter')
- params = {
- crc_token: 'some_random',
- nonce: 'some_nonce',
- }
- get '/api/v1/channels_twitter_webhook', params: params, headers: { 'x-twitter-webhooks-signature' => 'something' }, as: :json
- expect(response).to have_http_status(200)
- expect(json_response['response_token']).to eq('sha256=VE19eUk6krbdSqWPdvH71xtFhApBAU81uPW3UT65vOs=')
+ describe 'confirming authenticity of incoming Twitter webhook' do
+ context 'with valid headers & parameters' do
+ it 'returns 200 success' do
+ post '/api/v1/channels_twitter_webhook',
+ params: { for_user_id: channel.options[:user][:id], key: 'value' },
+ headers: { 'x-twitter-webhooks-signature' => 'sha256=JjEmBe1lVKT8XldrYUKibF+D5ehp8f0jDk3PXZSHEWI=' },
+ as: :json
+
+ expect(response).to have_http_status(200)
+ end
+ end
+
+ context 'when request is missing x-twitter-webhooks-signature header' do
+ it 'returns 422 with error message' do
+ post '/api/v1/channels_twitter_webhook', as: :json
+
+ expect(response).to have_http_status(422)
+ expect(json_response).to include('error' => "Missing 'x-twitter-webhooks-signature' header")
+ end
+ end
+
+ context 'when Zammad has no Twitter credentials (in DB or cache)' do
+ let!(:external_credential) { nil }
+ let!(:channel) { nil }
+
+ it 'returns 422 with error message' do
+ post '/api/v1/channels_twitter_webhook',
+ headers: { 'x-twitter-webhooks-signature' => 'something' },
+ as: :json
+
+ expect(response).to have_http_status(422)
+ expect(json_response).to include('error' => "No such external_credential 'twitter'!")
+ end
+ end
+
+ context 'with invalid token in x-twitter-webhooks-signature header' do
+ it 'returns 401 with error message' do
+ post '/api/v1/channels_twitter_webhook',
+ headers: { 'x-twitter-webhooks-signature' => 'something' },
+ as: :json
+
+ expect(response).to have_http_status(401)
+ expect(json_response).to include('error' => 'Not authorized')
+ end
+ end
+
+ context 'with :for_user_id request parameter' do
+ it 'returns 422 with error message' do
+ post '/api/v1/channels_twitter_webhook',
+ params: { key: 'value' },
+ headers: { 'x-twitter-webhooks-signature' => 'sha256=EERHBy/k17v+SuT+K0OXuwhJtKnPtxi0n/Y4Wye4kVU=' },
+ as: :json
+
+ expect(response).to have_http_status(422)
+ expect(json_response).to include('error' => "Missing 'for_user_id' in payload!")
+ end
+ end
+
+ context 'with invalid :for_user_id request parameter' do
+ it 'returns 422 with error message' do
+ post '/api/v1/channels_twitter_webhook',
+ params: { for_user_id: 'not_existing', key: 'value' },
+ headers: { 'x-twitter-webhooks-signature' => 'sha256=QaJiQl/4WRp/GF37b+eAdF6kPgptjDCLOgAIIbB1s0I=' },
+ as: :json
+
+ expect(response).to have_http_status(422)
+ expect(json_response).to include('error' => "No such channel for user id 'not_existing'!")
+ end
+ end
end
- end
+ describe 'auto-creation of tickets/articles on webhook receipt' do
+ let(:webhook_payload) do
+ JSON.parse(File.read(Rails.root.join('test', 'data', 'twitter', payload_file))).symbolize_keys
+ end
- describe 'request incoming - base' do
+ context 'for outbound DMs' do
+ context 'not matching any admin-defined filters' do
+ let(:payload_file) { 'webhook1_direct_message.json' }
- it 'does without x-twitter-webhooks-signature header check' do
- params = {}
- post '/api/v1/channels_twitter_webhook', params: params, as: :json
- expect(response).to have_http_status(422)
- expect(json_response['error']).to eq('Missing \'x-twitter-webhooks-signature\' header')
+ it 'returns 200' do
+ post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'creates closed ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .to change { Ticket.count }.by(1)
+
+ expect(Ticket.last.attributes)
+ .to include(
+ 'title' => 'Hey! Hello!',
+ 'state_id' => Ticket::State.find_by(name: 'closed').id,
+ 'priority_id' => Ticket::Priority.find_by(name: '2 normal').id,
+ 'customer_id' => User.find_by(login: 'zammadhq', firstname: 'Zammad', lastname: 'Hq').id,
+ 'created_by_id' => User.find_by(login: 'zammadhq', firstname: 'Zammad', lastname: 'Hq').id
+ )
+ end
+
+ it 'creates first article on closed ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .to change { Ticket::Article.count }.by(1)
+
+ expect(Ticket::Article.last.attributes)
+ .to include(
+ 'from' => '@zammadhq',
+ 'to' => '@medenhofer',
+ 'message_id' => '1062015437679050760',
+ 'created_by_id' => User.find_by(login: 'zammadhq', firstname: 'Zammad', lastname: 'Hq').id
+ )
+ end
+
+ it 'does not add any attachments to newly created ticket' do
+ post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json
+
+ expect(Ticket::Article.last.attachments).to be_empty
+ end
+ end
+ end
+
+ context 'for inbound DMs' do
+ context 'matching admin-defined #hashtag filter, with a link to an image' do
+ let(:payload_file) { 'webhook2_direct_message.json' }
+
+ it 'returns 200' do
+ post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'creates new ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .to change { Ticket.count }.by(1)
+
+ expect(Ticket.last.attributes)
+ .to include(
+ 'title' => 'Hello Zammad #zammad @znuny Yeah! https://t.co/UfaCwi9cUb',
+ 'state_id' => Ticket::State.find_by(name: 'new').id,
+ 'priority_id' => Ticket::Priority.find_by(name: '2 normal').id,
+ 'customer_id' => User.find_by(login: 'medenhofer', firstname: 'Martin', lastname: 'Edenhofer').id,
+ )
+ end
+
+ it 'creates first article on new ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .to change { Ticket::Article.count }.by(1)
+
+ expect(Ticket::Article.last.attributes)
+ .to include(
+ 'to' => '@zammadhq',
+ 'from' => '@medenhofer',
+ 'body' => "Hello Zammad #zammad @znuny\n\nYeah! https://twitter.com/messages/media/1063077238797725700",
+ 'message_id' => '1063077238797725700',
+ 'created_by_id' => User.find_by(login: 'medenhofer', firstname: 'Martin', lastname: 'Edenhofer').id
+ )
+ end
+
+ it 'does not add linked image as attachment to newly created ticket' do
+ post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json
+
+ expect(Ticket::Article.last.attachments).to be_empty
+ end
+ end
+
+ context 'from same sender as previously imported DMs' do
+ let(:payload_file) { 'webhook3_direct_message.json' }
+
+ before { post '/api/v1/channels_twitter_webhook', **previous_webhook_payload, as: :json }
+
+ let(:previous_webhook_payload) do
+ JSON.parse(File.read(Rails.root.join('test', 'data', 'twitter', 'webhook2_direct_message.json'))).symbolize_keys
+ end
+
+ it 'returns 200' do
+ post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'does not create new ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .not_to change { Ticket.count }
+ end
+
+ it 'adds new article to existing, open ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .to change { Ticket::Article.count }.by(1)
+
+ expect(Ticket::Article.last.attributes)
+ .to include(
+ 'to' => '@zammadhq',
+ 'from' => '@medenhofer',
+ 'body' => 'Hello again!',
+ 'message_id' => '1063077238797725701',
+ 'created_by_id' => User.find_by(login: 'medenhofer', firstname: 'Martin', lastname: 'Edenhofer').id,
+ 'ticket_id' => Ticket.find_by(title: 'Hello Zammad #zammad @znuny Yeah! https://t.co/UfaCwi9cUb').id
+ )
+ end
+
+ it 'does not add any attachments to newly created ticket' do
+ post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json
+
+ expect(Ticket::Article.last.attachments).to be_empty
+ end
+ end
+ end
+
+ context 'when receiving duplicate DMs' do
+ let(:payload_file) { 'webhook1_direct_message.json' }
+
+ it 'still returns 200' do
+ 2.times { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'does not create duplicate articles' do
+ expect do
+ 2.times { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ end.to change { Ticket::Article.count }.by(1)
+ end
+ end
+
+ context 'for tweets' do
+ context 'matching admin-defined #hashtag filter, with an image link' do
+ let(:payload_file) { 'webhook1_tweet.json' }
+
+ before do
+ stub_request(:get, 'http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_bigger.jpg')
+ .to_return(status: 200, body: 'some_content')
+
+ stub_request(:get, 'https://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg')
+ .to_return(status: 200, body: 'some_content')
+ end
+
+ it 'returns 200' do
+ post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'creates a closed ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .to change { Ticket.count }.by(1)
+
+ expect(Ticket.last.attributes)
+ .to include(
+ 'title' => 'Hey @medenhofer ! #hello1234 https://t.co/f1kffFlwpN',
+ 'state_id' => Ticket::State.find_by(name: 'closed').id,
+ 'priority_id' => Ticket::Priority.find_by(name: '2 normal').id,
+ 'customer_id' => User.find_by(login: 'zammadhq', firstname: 'Zammad', lastname: 'Hq').id,
+ 'created_by_id' => User.find_by(login: 'zammadhq', firstname: 'Zammad', lastname: 'Hq').id,
+ )
+ end
+
+ it 'creates first article on closed ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .to change { Ticket::Article.count }.by(1)
+
+ expect(Ticket::Article.last.attributes)
+ .to include(
+ 'from' => '@zammadhq',
+ 'to' => '@medenhofer',
+ 'body' => 'Hey @medenhofer ! #hello1234 https://twitter.com/zammadhq/status/1063212927510081536/photo/1',
+ 'message_id' => '1063212927510081536',
+ 'created_by_id' => User.find_by(login: 'zammadhq', firstname: 'Zammad', lastname: 'Hq').id
+ )
+ end
+
+ it 'add linked image as attachment to newly created article' do
+ expect(Ticket::Article.last.attachments)
+ .to match_array(Store.where(filename: 'DsFKfJRWkAAFEbo.jpg'))
+ end
+ end
+
+ context 'longer than 140 characters (with no media links)' do
+ let(:payload_file) { 'webhook2_tweet.json' }
+
+ before do
+ stub_request(:get, 'http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_bigger.jpg')
+ .to_return(status: 200, body: 'some_content')
+ end
+
+ it 'returns 200' do
+ post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'creates a new ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .to change { Ticket.count }.by(1)
+
+ expect(Ticket.last.attributes)
+ .to include(
+ 'title' => '@znuny Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ...',
+ 'state_id' => Ticket::State.find_by(name: 'new').id,
+ 'priority_id' => Ticket::Priority.find_by(name: '2 normal').id,
+ 'customer_id' => User.find_by(login: 'medenhofer', firstname: 'Martin', lastname: 'Edenhofer').id,
+ 'created_by_id' => User.find_by(login: 'medenhofer', firstname: 'Martin', lastname: 'Edenhofer').id,
+ )
+ end
+
+ it 'creates first article on new ticket' do
+ expect { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ .to change { Ticket::Article.count }.by(1)
+
+ expect(Ticket::Article.last.attributes)
+ .to include(
+ 'from' => '@medenhofer',
+ 'to' => '@znuny',
+ 'body' => '@znuny Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lore',
+ 'created_by_id' => User.find_by(login: 'medenhofer', firstname: 'Martin', lastname: 'Edenhofer').id,
+ 'message_id' => '1065035365336141825'
+ )
+ end
+
+ it 'does not add any attachments to newly created ticket' do
+ post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json
+
+ expect(Ticket::Article.last.attachments).to be_empty
+ end
+ end
+
+ context 'when receiving duplicate messages' do
+ let(:payload_file) { 'webhook1_tweet.json' }
+
+ it 'still returns 200' do
+ 2.times { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+
+ expect(response).to have_http_status(200)
+ end
+
+ it 'does not create duplicate articles' do
+ expect do
+ 2.times { post '/api/v1/channels_twitter_webhook', **webhook_payload, as: :json }
+ end.to change { Ticket::Article.count }.by(1)
+ end
+ end
+ end
end
-
- it 'does no external_credential check' do
- @external_credential.destroy
- params = {}
- post '/api/v1/channels_twitter_webhook', params: params, headers: { 'x-twitter-webhooks-signature' => 'something' }, as: :json
- expect(response).to have_http_status(422)
- expect(json_response['error']).to eq('No such external_credential \'twitter\'!')
- end
-
- it 'does invalid token check' do
- params = {}
- post '/api/v1/channels_twitter_webhook', params: params, headers: { 'x-twitter-webhooks-signature' => 'something' }, as: :json
- expect(response).to have_http_status(401)
- expect(json_response['error']).to eq('Not authorized')
- end
-
- it 'does existing for_user_id check' do
- params = { key: 'value' }
- post '/api/v1/channels_twitter_webhook', params: params, headers: { 'x-twitter-webhooks-signature' => 'sha256=EERHBy/k17v+SuT+K0OXuwhJtKnPtxi0n/Y4Wye4kVU=' }, as: :json
- expect(response).to have_http_status(422)
- expect(json_response['error']).to eq('Missing \'for_user_id\' in payload!')
- end
-
- it 'does invalid user check' do
- params = { for_user_id: 'not_existing', key: 'value' }
- post '/api/v1/channels_twitter_webhook', params: params, headers: { 'x-twitter-webhooks-signature' => 'sha256=QaJiQl/4WRp/GF37b+eAdF6kPgptjDCLOgAIIbB1s0I=' }, as: :json
- expect(response).to have_http_status(422)
- expect(json_response['error']).to eq('No such channel for user id \'not_existing\'!')
- end
-
- it 'does valid token check' do
- params = { for_user_id: 123, key: 'value' }
- post '/api/v1/channels_twitter_webhook', params: params, headers: { 'x-twitter-webhooks-signature' => 'sha256=JjEmBe1lVKT8XldrYUKibF+D5ehp8f0jDk3PXZSHEWI=' }, as: :json
- expect(response).to have_http_status(200)
- end
- end
-
- describe 'request incoming direct message' do
- it 'create new ticket via tweet' do
- post '/api/v1/channels_twitter_webhook', params: read_messaage('webhook1_direct_message'), headers: { 'x-twitter-webhooks-signature' => 'sha256=xXu7qrPhqXfo8Ot14c0si9HrdQdBNru5fkSdoMZi+Ms=' }, as: :json
-
- expect(response).to have_http_status(200)
- article = Ticket::Article.find_by(message_id: '1062015437679050760')
- expect(article).to be_present
- expect(article.from).to eq('@zammadhq')
- expect(article.to).to eq('@medenhofer')
- expect(article.created_by.login).to eq('zammadhq')
- expect(article.created_by.firstname).to eq('Zammad')
- expect(article.created_by.lastname).to eq('Hq')
- expect(article.attachments.count).to eq(0)
-
- ticket = article.ticket
- expect(ticket.title).to eq('Hey! Hello!')
- expect(ticket.state.name).to eq('closed')
- expect(ticket.priority.name).to eq('2 normal')
- expect(ticket.customer.login).to eq('zammadhq')
- expect(ticket.customer.firstname).to eq('Zammad')
- expect(ticket.customer.lastname).to eq('Hq')
- expect(ticket.created_by.login).to eq('zammadhq')
- expect(ticket.created_by.firstname).to eq('Zammad')
- expect(ticket.created_by.lastname).to eq('Hq')
-
- post '/api/v1/channels_twitter_webhook', params: read_messaage('webhook2_direct_message'), headers: { 'x-twitter-webhooks-signature' => 'sha256=wYiCk7gfAgrnerCpj3XD58hozfVDjcQvcYPZCFH+stU=' }, as: :json
-
- article = Ticket::Article.find_by(message_id: '1063077238797725700')
- expect(article).to be_present
- expect(article.to).to eq('@zammadhq')
- expect(article.from).to eq('@medenhofer')
- expect(article.body).to eq("Hello Zammad #zammad @znuny\n\nYeah! https://twitter.com/messages/media/1063077238797725700")
- expect(article.created_by.login).to eq('medenhofer')
- expect(article.created_by.firstname).to eq('Martin')
- expect(article.created_by.lastname).to eq('Edenhofer')
- expect(article.attachments.count).to eq(0)
-
- ticket = article.ticket
- expect(ticket.title).to eq('Hello Zammad #zammad @znuny Yeah! https://t.co/UfaCwi9cUb')
- expect(ticket.state.name).to eq('new')
- expect(ticket.priority.name).to eq('2 normal')
- expect(ticket.customer.login).to eq('medenhofer')
- expect(ticket.customer.firstname).to eq('Martin')
- expect(ticket.customer.lastname).to eq('Edenhofer')
-
- post '/api/v1/channels_twitter_webhook', params: read_messaage('webhook3_direct_message'), headers: { 'x-twitter-webhooks-signature' => 'sha256=OTguUdchBdxNal/csZsRkytKL5srrUuezZ3hp/2E404=' }, as: :json
-
- article = Ticket::Article.find_by(message_id: '1063077238797725701')
- expect(article).to be_present
- expect(article.to).to eq('@zammadhq')
- expect(article.from).to eq('@medenhofer')
- expect(article.body).to eq('Hello again!')
- expect(article.created_by.login).to eq('medenhofer')
- expect(article.created_by.firstname).to eq('Martin')
- expect(article.created_by.lastname).to eq('Edenhofer')
- expect(article.ticket.id).to eq(ticket.id)
- expect(article.attachments.count).to eq(0)
-
- ticket = article.ticket
- expect(ticket.title).to eq('Hello Zammad #zammad @znuny Yeah! https://t.co/UfaCwi9cUb')
- expect(ticket.state.name).to eq('new')
- expect(ticket.priority.name).to eq('2 normal')
- expect(ticket.customer.login).to eq('medenhofer')
- expect(ticket.customer.firstname).to eq('Martin')
- expect(ticket.customer.lastname).to eq('Edenhofer')
- end
-
- it 'check duplicate' do
- post '/api/v1/channels_twitter_webhook', params: read_messaage('webhook1_direct_message'), headers: { 'x-twitter-webhooks-signature' => 'sha256=xXu7qrPhqXfo8Ot14c0si9HrdQdBNru5fkSdoMZi+Ms=' }, as: :json
-
- expect(response).to have_http_status(200)
-
- post '/api/v1/channels_twitter_webhook', params: read_messaage('webhook1_direct_message'), headers: { 'x-twitter-webhooks-signature' => 'sha256=xXu7qrPhqXfo8Ot14c0si9HrdQdBNru5fkSdoMZi+Ms=' }, as: :json
-
- expect(response).to have_http_status(200)
-
- expect(Ticket::Article.where(message_id: '1062015437679050760').count).to eq(1)
- end
- end
-
- describe 'request incoming direct message' do
-
- it 'create new ticket via tweet' do
-
- stub_request(:get, 'http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_bigger.jpg')
- .to_return(status: 200, body: 'some_content')
-
- stub_request(:get, 'https://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg')
- .to_return(status: 200, body: 'some_content')
-
- post '/api/v1/channels_twitter_webhook', params: read_messaage('webhook1_tweet'), headers: { 'x-twitter-webhooks-signature' => 'sha256=DmARpz6wdgte6Vj+ePeqC+RHvEDokmwOIIqr4//utkk=' }, as: :json
-
- expect(response).to have_http_status(200)
- article = Ticket::Article.find_by(message_id: '1063212927510081536')
- expect(article).to be_present
- expect(article.from).to eq('@zammadhq')
- expect(article.to).to eq('@medenhofer')
- expect(article.body).to eq('Hey @medenhofer ! #hello1234 https://twitter.com/zammadhq/status/1063212927510081536/photo/1')
- expect(article.created_by.login).to eq('zammadhq')
- expect(article.created_by.firstname).to eq('Zammad')
- expect(article.created_by.lastname).to eq('Hq')
- expect(article.attachments.count).to eq(1)
- expect(article.attachments[0].filename).to eq('DsFKfJRWkAAFEbo.jpg')
-
- ticket = article.ticket
- expect(ticket.title).to eq('Hey @medenhofer ! #hello1234 https://t.co/f1kffFlwpN')
- expect(ticket.state.name).to eq('closed')
- expect(ticket.priority.name).to eq('2 normal')
- expect(ticket.customer.login).to eq('zammadhq')
- expect(ticket.customer.firstname).to eq('Zammad')
- expect(ticket.customer.lastname).to eq('Hq')
- expect(ticket.created_by.login).to eq('zammadhq')
- expect(ticket.created_by.firstname).to eq('Zammad')
- expect(ticket.created_by.lastname).to eq('Hq')
- end
-
- it 'create new ticket via tweet extended_tweet' do
-
- stub_request(:get, 'http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_bigger.jpg')
- .to_return(status: 200, body: 'some_content')
-
- post '/api/v1/channels_twitter_webhook', params: read_messaage('webhook2_tweet'), headers: { 'x-twitter-webhooks-signature' => 'sha256=U7bglX19JitI2xuvyONAc0d/fowIFEeUzkEgnWdGyUM=' }, as: :json
-
- expect(response).to have_http_status(200)
- article = Ticket::Article.find_by(message_id: '1065035365336141825')
- expect(article).to be_present
- expect(article.from).to eq('@medenhofer')
- expect(article.to).to eq('@znuny')
- expect(article.body).to eq('@znuny Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lore')
- expect(article.created_by.login).to eq('medenhofer')
- expect(article.created_by.firstname).to eq('Martin')
- expect(article.created_by.lastname).to eq('Edenhofer')
- expect(article.attachments.count).to eq(0)
-
- ticket = article.ticket
- expect(ticket.title).to eq('@znuny Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy ...')
- expect(ticket.state.name).to eq('new')
- expect(ticket.priority.name).to eq('2 normal')
- expect(ticket.customer.login).to eq('medenhofer')
- expect(ticket.customer.firstname).to eq('Martin')
- expect(ticket.customer.lastname).to eq('Edenhofer')
- expect(ticket.created_by.login).to eq('medenhofer')
- expect(ticket.created_by.firstname).to eq('Martin')
- expect(ticket.created_by.lastname).to eq('Edenhofer')
- end
-
- it 'check duplicate' do
- post '/api/v1/channels_twitter_webhook', params: read_messaage('webhook1_tweet'), headers: { 'x-twitter-webhooks-signature' => 'sha256=DmARpz6wdgte6Vj+ePeqC+RHvEDokmwOIIqr4//utkk=' }, as: :json
-
- expect(response).to have_http_status(200)
-
- post '/api/v1/channels_twitter_webhook', params: read_messaage('webhook1_tweet'), headers: { 'x-twitter-webhooks-signature' => 'sha256=DmARpz6wdgte6Vj+ePeqC+RHvEDokmwOIIqr4//utkk=' }, as: :json
-
- expect(response).to have_http_status(200)
-
- expect(Ticket::Article.where(message_id: '1063212927510081536').count).to eq(1)
- end
- end
-
- def read_messaage(file)
- JSON.parse(File.read(Rails.root.join('test', 'data', 'twitter', "#{file}.json")))
end
end
diff --git a/test/data/twitter/webhook1_direct_message.json b/test/data/twitter/webhook1_direct_message.json
index a05f62582..f295ecbfa 100644
--- a/test/data/twitter/webhook1_direct_message.json
+++ b/test/data/twitter/webhook1_direct_message.json
@@ -1,65 +1,70 @@
{
- "for_user_id": "123",
- "direct_message_events": [
- {
- "type": "message_create",
- "id": "1062015437679050760",
- "created_timestamp": "1542039186292",
- "message_create": {
- "target": {
- "recipient_id": "456"
- },
- "sender_id": "123",
- "source_app_id": "268278",
- "message_data": {
- "text": "Hey! Hello!",
- "entities": {
- "hashtags": [],
- "symbols": [],
- "user_mentions": [],
- "urls": []
+ "headers" : {
+ "x-twitter-webhooks-signature" : "sha256=xXu7qrPhqXfo8Ot14c0si9HrdQdBNru5fkSdoMZi+Ms="
+ },
+ "params" : {
+ "for_user_id": "123",
+ "direct_message_events": [
+ {
+ "type": "message_create",
+ "id": "1062015437679050760",
+ "created_timestamp": "1542039186292",
+ "message_create": {
+ "target": {
+ "recipient_id": "456"
+ },
+ "sender_id": "123",
+ "source_app_id": "268278",
+ "message_data": {
+ "text": "Hey! Hello!",
+ "entities": {
+ "hashtags": [],
+ "symbols": [],
+ "user_mentions": [],
+ "urls": []
+ }
}
}
}
- }
- ],
- "apps": {
- "268278": {
- "id": "268278",
- "name": "Twitter Web Client",
- "url": "http://twitter.com"
- }
- },
- "users": {
- "123": {
- "id": "123",
- "created_timestamp": "1476091912921",
- "name": "Zammad HQ",
- "screen_name": "zammadhq",
- "description": "Helpdesk and Customer Support made easy. Open Source for download or to go with SaaS. #zammad",
- "url": "https://t.co/XITyrXmhTP",
- "protected": false,
- "verified": false,
- "followers_count": 426,
- "friends_count": 509,
- "statuses_count": 436,
- "profile_image_url": "http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg",
- "profile_image_url_https": "https://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg"
+ ],
+ "apps": {
+ "268278": {
+ "id": "268278",
+ "name": "Twitter Web Client",
+ "url": "http://twitter.com"
+ }
},
- "456": {
- "id": "456",
- "created_timestamp": "1290730789000",
- "name": "Martin Edenhofer",
- "screen_name": "medenhofer",
- "description": "Open Source professional and geek. Also known as #OTRS and #Zammad inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
- "url": "https://t.co/whm4HTWdMw",
- "protected": false,
- "verified": false,
- "followers_count": 312,
- "friends_count": 314,
- "statuses_count": 222,
- "profile_image_url": "http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
- "profile_image_url_https": "https://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg"
+ "users": {
+ "123": {
+ "id": "123",
+ "created_timestamp": "1476091912921",
+ "name": "Zammad HQ",
+ "screen_name": "zammadhq",
+ "description": "Helpdesk and Customer Support made easy. Open Source for download or to go with SaaS. #zammad",
+ "url": "https://t.co/XITyrXmhTP",
+ "protected": false,
+ "verified": false,
+ "followers_count": 426,
+ "friends_count": 509,
+ "statuses_count": 436,
+ "profile_image_url": "http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg",
+ "profile_image_url_https": "https://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg"
+ },
+ "456": {
+ "id": "456",
+ "created_timestamp": "1290730789000",
+ "name": "Martin Edenhofer",
+ "screen_name": "medenhofer",
+ "description": "Open Source professional and geek. Also known as #OTRS and #Zammad inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
+ "url": "https://t.co/whm4HTWdMw",
+ "protected": false,
+ "verified": false,
+ "followers_count": 312,
+ "friends_count": 314,
+ "statuses_count": 222,
+ "profile_image_url": "http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
+ "profile_image_url_https": "https://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg"
+ }
}
}
-}
\ No newline at end of file
+}
diff --git a/test/data/twitter/webhook1_tweet.json b/test/data/twitter/webhook1_tweet.json
index 75127b31a..0ff0452f0 100644
--- a/test/data/twitter/webhook1_tweet.json
+++ b/test/data/twitter/webhook1_tweet.json
@@ -1,162 +1,167 @@
{
- "for_user_id": "123",
- "tweet_create_events": [
- {
- "created_at": "Thu Nov 15 23:31:30 +0000 2018",
- "id": 1063212927510081536,
- "id_str": "1063212927510081536",
- "text": "Hey @medenhofer ! #hello1234 https://t.co/f1kffFlwpN",
- "display_text_range": [0, 29],
- "source": "Twitter Web Client",
- "truncated": false,
- "in_reply_to_status_id": null,
- "in_reply_to_status_id_str": null,
- "in_reply_to_user_id": null,
- "in_reply_to_user_id_str": null,
- "in_reply_to_screen_name": null,
- "user": {
- "id": 123,
- "id_str": "123",
- "name": "Zammad HQ",
- "screen_name": "zammadhq",
- "location": null,
- "url": "http://zammad.com",
- "description": "Helpdesk and Customer Support made easy. Open Source for download or to go with SaaS. #zammad",
- "translator_type": "none",
- "protected": false,
- "verified": false,
- "followers_count": 427,
- "friends_count": 512,
- "listed_count": 20,
- "favourites_count": 280,
- "statuses_count": 438,
- "created_at": "Mon Oct 10 09:31:52 +0000 2016",
- "utc_offset": null,
- "time_zone": null,
- "geo_enabled": false,
- "lang": "en",
- "contributors_enabled": false,
- "is_translator": false,
- "profile_background_color": "000000",
- "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
- "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
- "profile_background_tile": false,
- "profile_link_color": "31B068",
- "profile_sidebar_border_color": "000000",
- "profile_sidebar_fill_color": "000000",
- "profile_text_color": "000000",
- "profile_use_background_image": false,
- "profile_image_url": "http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg", "profile_image_url_https": "https://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg",
- "profile_banner_url": "https://pbs.twimg.com/profile_banners/123/1476097853",
- "default_profile": false,
- "default_profile_image": false,
- "following": null,
- "follow_request_sent": null,
- "notifications": null
- },
- "geo": null,
- "coordinates": null,
- "place": null,
- "contributors": null,
- "is_quote_status": false,
- "quote_count": 0,
- "reply_count": 0,
- "retweet_count": 0,
- "favorite_count": 0,
- "entities": {
- "hashtags": [
- {"text": "hello1234", "indices": [19, 29]}
- ],
- "urls": [],
- "user_mentions": [
- {
- "screen_name": "medenhofer",
- "name": "Martin Edenhofer",
- "id": 456,
- "id_str": "456",
- "indices": [4, 15]
- }
- ],
- "symbols": [],
- "media": [
- {
- "id": 1063212885961248768,
- "id_str": "1063212885961248768",
- "indices": [30, 53],
- "media_url": "http://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg",
- "media_url_https": "https://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg",
- "url": "https://t.co/f1kffFlwpN",
- "display_url": "pic.twitter.com/f1kffFlwpN",
- "expanded_url": "https://twitter.com/zammadhq/status/1063212927510081536/photo/1",
- "type": "photo",
- "sizes": {
- "thumb": {
- "w": 150,
- "h": 150,
- "resize": "crop"
- },
- "large": {
- "w": 852,
- "h": 462,
- "resize": "fit"
- },
- "medium": {
- "w": 852,
- "h": 462,
- "resize": "fit"
- },
- "small": {
- "w": 680,
- "h": 369,
- "resize": "fit"
+ "headers": {
+ "x-twitter-webhooks-signature": "sha256=DmARpz6wdgte6Vj+ePeqC+RHvEDokmwOIIqr4//utkk="
+ },
+ "params": {
+ "for_user_id": "123",
+ "tweet_create_events": [
+ {
+ "created_at": "Thu Nov 15 23:31:30 +0000 2018",
+ "id": 1063212927510081536,
+ "id_str": "1063212927510081536",
+ "text": "Hey @medenhofer ! #hello1234 https://t.co/f1kffFlwpN",
+ "display_text_range": [0, 29],
+ "source": "Twitter Web Client",
+ "truncated": false,
+ "in_reply_to_status_id": null,
+ "in_reply_to_status_id_str": null,
+ "in_reply_to_user_id": null,
+ "in_reply_to_user_id_str": null,
+ "in_reply_to_screen_name": null,
+ "user": {
+ "id": 123,
+ "id_str": "123",
+ "name": "Zammad HQ",
+ "screen_name": "zammadhq",
+ "location": null,
+ "url": "http://zammad.com",
+ "description": "Helpdesk and Customer Support made easy. Open Source for download or to go with SaaS. #zammad",
+ "translator_type": "none",
+ "protected": false,
+ "verified": false,
+ "followers_count": 427,
+ "friends_count": 512,
+ "listed_count": 20,
+ "favourites_count": 280,
+ "statuses_count": 438,
+ "created_at": "Mon Oct 10 09:31:52 +0000 2016",
+ "utc_offset": null,
+ "time_zone": null,
+ "geo_enabled": false,
+ "lang": "en",
+ "contributors_enabled": false,
+ "is_translator": false,
+ "profile_background_color": "000000",
+ "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
+ "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
+ "profile_background_tile": false,
+ "profile_link_color": "31B068",
+ "profile_sidebar_border_color": "000000",
+ "profile_sidebar_fill_color": "000000",
+ "profile_text_color": "000000",
+ "profile_use_background_image": false,
+ "profile_image_url": "http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg", "profile_image_url_https": "https://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg",
+ "profile_banner_url": "https://pbs.twimg.com/profile_banners/123/1476097853",
+ "default_profile": false,
+ "default_profile_image": false,
+ "following": null,
+ "follow_request_sent": null,
+ "notifications": null
+ },
+ "geo": null,
+ "coordinates": null,
+ "place": null,
+ "contributors": null,
+ "is_quote_status": false,
+ "quote_count": 0,
+ "reply_count": 0,
+ "retweet_count": 0,
+ "favorite_count": 0,
+ "entities": {
+ "hashtags": [
+ {"text": "hello1234", "indices": [19, 29]}
+ ],
+ "urls": [],
+ "user_mentions": [
+ {
+ "screen_name": "medenhofer",
+ "name": "Martin Edenhofer",
+ "id": 456,
+ "id_str": "456",
+ "indices": [4, 15]
+ }
+ ],
+ "symbols": [],
+ "media": [
+ {
+ "id": 1063212885961248768,
+ "id_str": "1063212885961248768",
+ "indices": [30, 53],
+ "media_url": "http://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg",
+ "media_url_https": "https://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg",
+ "url": "https://t.co/f1kffFlwpN",
+ "display_url": "pic.twitter.com/f1kffFlwpN",
+ "expanded_url": "https://twitter.com/zammadhq/status/1063212927510081536/photo/1",
+ "type": "photo",
+ "sizes": {
+ "thumb": {
+ "w": 150,
+ "h": 150,
+ "resize": "crop"
+ },
+ "large": {
+ "w": 852,
+ "h": 462,
+ "resize": "fit"
+ },
+ "medium": {
+ "w": 852,
+ "h": 462,
+ "resize": "fit"
+ },
+ "small": {
+ "w": 680,
+ "h": 369,
+ "resize": "fit"
+ }
}
}
- }
- ]
- },
- "extended_entities": {
- "media": [
- {
- "id": 1063212885961248768,
- "id_str": "1063212885961248768",
- "indices": [30, 53],
- "media_url": "http://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg",
- "media_url_https": "https://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg",
- "url": "https://t.co/f1kffFlwpN",
- "display_url": "pic.twitter.com/f1kffFlwpN",
- "expanded_url": "https://twitter.com/zammadhq/status/1063212927510081536/photo/1",
- "type": "photo",
- "sizes": {
- "thumb": {
- "w": 150,
- "h": 150,
- "resize": "crop"
- },
- "large": {
- "w": 852,
- "h": 462,
- "resize": "fit"
- },
- "medium": {
- "w": 852,
- "h": 462,
- "resize": "fit"
- },
- "small": {
- "w": 680,
- "h": 369,
- "resize": "fit"
+ ]
+ },
+ "extended_entities": {
+ "media": [
+ {
+ "id": 1063212885961248768,
+ "id_str": "1063212885961248768",
+ "indices": [30, 53],
+ "media_url": "http://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg",
+ "media_url_https": "https://pbs.twimg.com/media/DsFKfJRWkAAFEbo.jpg",
+ "url": "https://t.co/f1kffFlwpN",
+ "display_url": "pic.twitter.com/f1kffFlwpN",
+ "expanded_url": "https://twitter.com/zammadhq/status/1063212927510081536/photo/1",
+ "type": "photo",
+ "sizes": {
+ "thumb": {
+ "w": 150,
+ "h": 150,
+ "resize": "crop"
+ },
+ "large": {
+ "w": 852,
+ "h": 462,
+ "resize": "fit"
+ },
+ "medium": {
+ "w": 852,
+ "h": 462,
+ "resize": "fit"
+ },
+ "small": {
+ "w": 680,
+ "h": 369,
+ "resize": "fit"
+ }
}
}
- }
- ]
- },
- "favorited": false,
- "retweeted": false,
- "possibly_sensitive": false,
- "filter_level": "low",
- "lang": "und",
- "timestamp_ms": "1542324690116"
- }
- ]
+ ]
+ },
+ "favorited": false,
+ "retweeted": false,
+ "possibly_sensitive": false,
+ "filter_level": "low",
+ "lang": "und",
+ "timestamp_ms": "1542324690116"
+ }
+ ]
+ }
}
diff --git a/test/data/twitter/webhook2_direct_message.json b/test/data/twitter/webhook2_direct_message.json
index eedc679e9..fec2a5884 100644
--- a/test/data/twitter/webhook2_direct_message.json
+++ b/test/data/twitter/webhook2_direct_message.json
@@ -1,113 +1,118 @@
{
- "for_user_id": "123",
- "direct_message_events": [
- {
- "type": "message_create",
- "id": "1063077238797725700",
- "created_timestamp": "1542292339406",
- "message_create": {
- "target": {
- "recipient_id": "123"
- },
- "sender_id": "456",
- "message_data": {
- "text": "Hello Zammad #zammad @znuny\n\nYeah! https://t.co/UfaCwi9cUb",
- "entities": {
- "hashtags": [
- {
- "text": "zammad",
- "indices": [13,20]
- }
- ],
- "symbols": [],
- "user_mentions": [
- {
- "screen_name": "znuny",
- "name": "Znuny / ES for OTRS",
- "id": 789,
- "id_str": "789",
- "indices": [21, 27]
- }
- ],
- "urls": [
- {
- "url": "https://t.co/UfaCwi9cUb",
- "expanded_url": "https://twitter.com/messages/media/1063077238797725700",
- "display_url": "pic.twitter.com/UfaCwi9cUb",
- "indices": [35, 58]
- }
- ]
+ "headers" : {
+ "x-twitter-webhooks-signature" : "sha256=wYiCk7gfAgrnerCpj3XD58hozfVDjcQvcYPZCFH+stU="
+ },
+ "params": {
+ "for_user_id": "123",
+ "direct_message_events": [
+ {
+ "type": "message_create",
+ "id": "1063077238797725700",
+ "created_timestamp": "1542292339406",
+ "message_create": {
+ "target": {
+ "recipient_id": "123"
},
- "attachment": {
- "type": "media",
- "media": {
- "id": 1063077198536556545,
- "id_str": "1063077198536556545",
- "indices": [35, 58],
- "media_url": "https://ton.twitter.com/1.1/ton/data/dm/1063077238797725700/1063077198536556545/9FZgsMdV.jpg",
- "media_url_https": "https://ton.twitter.com/1.1/ton/data/dm/1063077238797725700/1063077198536556545/9FZgsMdV.jpg",
- "url": "https://t.co/UfaCwi9cUb",
- "display_url": "pic.twitter.com/UfaCwi9cUb",
- "expanded_url": "https://twitter.com/messages/media/1063077238797725700",
- "type": "photo",
- "sizes": {
- "thumb": {
- "w": 150,
- "h": 150,
- "resize": "crop"
- },
- "medium": {
- "w": 1200,
- "h": 313,
- "resize": "fit"
- },
- "small": {
- "w": 680,
- "h": 177,
- "resize": "fit"
- },
- "large": {
- "w": 1472,
- "h": 384,
- "resize": "fit"
+ "sender_id": "456",
+ "message_data": {
+ "text": "Hello Zammad #zammad @znuny\n\nYeah! https://t.co/UfaCwi9cUb",
+ "entities": {
+ "hashtags": [
+ {
+ "text": "zammad",
+ "indices": [13,20]
+ }
+ ],
+ "symbols": [],
+ "user_mentions": [
+ {
+ "screen_name": "znuny",
+ "name": "Znuny / ES for OTRS",
+ "id": 789,
+ "id_str": "789",
+ "indices": [21, 27]
+ }
+ ],
+ "urls": [
+ {
+ "url": "https://t.co/UfaCwi9cUb",
+ "expanded_url": "https://twitter.com/messages/media/1063077238797725700",
+ "display_url": "pic.twitter.com/UfaCwi9cUb",
+ "indices": [35, 58]
+ }
+ ]
+ },
+ "attachment": {
+ "type": "media",
+ "media": {
+ "id": 1063077198536556545,
+ "id_str": "1063077198536556545",
+ "indices": [35, 58],
+ "media_url": "https://ton.twitter.com/1.1/ton/data/dm/1063077238797725700/1063077198536556545/9FZgsMdV.jpg",
+ "media_url_https": "https://ton.twitter.com/1.1/ton/data/dm/1063077238797725700/1063077198536556545/9FZgsMdV.jpg",
+ "url": "https://t.co/UfaCwi9cUb",
+ "display_url": "pic.twitter.com/UfaCwi9cUb",
+ "expanded_url": "https://twitter.com/messages/media/1063077238797725700",
+ "type": "photo",
+ "sizes": {
+ "thumb": {
+ "w": 150,
+ "h": 150,
+ "resize": "crop"
+ },
+ "medium": {
+ "w": 1200,
+ "h": 313,
+ "resize": "fit"
+ },
+ "small": {
+ "w": 680,
+ "h": 177,
+ "resize": "fit"
+ },
+ "large": {
+ "w": 1472,
+ "h": 384,
+ "resize": "fit"
+ }
}
}
}
}
}
}
- }
- ],
- "users": {
- "456": {
- "id": "456",
- "created_timestamp": "1290730789000",
- "name": "Martin Edenhofer",
- "screen_name": "medenhofer",
- "description": "Open Source professional and geek. Also known as #OTRS and #Zammad inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
- "url": "https://t.co/whm4HTWdMw",
- "protected": false,
- "verified": false,
- "followers_count": 312,
- "friends_count": 314,
- "statuses_count": 222,
- "profile_image_url": "http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
- "profile_image_url_https": "https://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg"
- },
- "123": {
- "id": "123",
- "created_timestamp": "1476091912921",
- "name": "Zammad HQ",
- "screen_name": "zammadhq",
- "description": "Helpdesk and Customer Support made easy. Open Source for download or to go with SaaS. #zammad",
- "url": "https://t.co/XITyrXmhTP",
- "protected": false,
- "verified": false,
- "followers_count": 427,
- "friends_count": 512,
- "statuses_count": 437,
- "profile_image_url": "http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg",
- "profile_image_url_https": "https://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg"
+ ],
+ "users": {
+ "456": {
+ "id": "456",
+ "created_timestamp": "1290730789000",
+ "name": "Martin Edenhofer",
+ "screen_name": "medenhofer",
+ "description": "Open Source professional and geek. Also known as #OTRS and #Zammad inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
+ "url": "https://t.co/whm4HTWdMw",
+ "protected": false,
+ "verified": false,
+ "followers_count": 312,
+ "friends_count": 314,
+ "statuses_count": 222,
+ "profile_image_url": "http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
+ "profile_image_url_https": "https://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg"
+ },
+ "123": {
+ "id": "123",
+ "created_timestamp": "1476091912921",
+ "name": "Zammad HQ",
+ "screen_name": "zammadhq",
+ "description": "Helpdesk and Customer Support made easy. Open Source for download or to go with SaaS. #zammad",
+ "url": "https://t.co/XITyrXmhTP",
+ "protected": false,
+ "verified": false,
+ "followers_count": 427,
+ "friends_count": 512,
+ "statuses_count": 437,
+ "profile_image_url": "http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg",
+ "profile_image_url_https": "https://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg"
+ }
}
}
}
diff --git a/test/data/twitter/webhook2_tweet.json b/test/data/twitter/webhook2_tweet.json
index f85a5ffef..55f371aed 100644
--- a/test/data/twitter/webhook2_tweet.json
+++ b/test/data/twitter/webhook2_tweet.json
@@ -1,68 +1,98 @@
{
- "for_user_id": "123",
- "tweet_create_events": [
- {
- "created_at": "Wed Nov 21 00:13:13 +0000 2018",
- "id": 1065035365336141825,
- "id_str": "1065035365336141825",
- "text": "@znuny Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et… https://t.co/b9woj0QXNZ",
- "source": "Twitter Web Client",
- "truncated": true,
- "in_reply_to_status_id": null,
- "in_reply_to_status_id_str": null,
- "in_reply_to_user_id": 123,
- "in_reply_to_user_id_str": "123",
- "in_reply_to_screen_name": "znuny",
- "user": {
- "id": 219826253,
- "id_str": "219826253",
- "name": "Martin Edenhofer",
- "screen_name": "medenhofer",
- "location": null,
- "url": "http://edenhofer.de/",
- "description": "Open Source professional and geek. Also known as #OTRS and #Zammad inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
- "translator_type": "regular",
- "protected": false,
- "verified": false,
- "followers_count": 310,
- "friends_count": 314,
- "listed_count": 16,
- "favourites_count": 129,
- "statuses_count": 225,
- "created_at": "Fri Nov 26 00:19:49 +0000 2010",
- "utc_offset": null,
- "time_zone": null,
- "geo_enabled": false,
- "lang": "en",
- "contributors_enabled": false,
- "is_translator": false,
- "profile_background_color": "C0DEED",
- "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
- "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
- "profile_background_tile": true, "profile_link_color": "0084B4", "profile_sidebar_border_color": "FFFFFF",
- "profile_sidebar_fill_color": "DDEEF6",
- "profile_text_color": "333333",
- "profile_use_background_image": true,
- "profile_image_url": "http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
- "profile_image_url_https": "https://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
- "profile_banner_url": "https://pbs.twimg.com/profile_banners/219826253/1349428277",
- "default_profile": false,
- "default_profile_image": false,
- "following": null,
- "follow_request_sent": null,
- "notifications": null
- },
- "geo": null,
- "coordinates": null,
- "place": null,
- "contributors": null,
- "is_quote_status": false,
- "extended_tweet": {
- "full_text": "@znuny Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lore",
- "display_text_range": [0, 279],
+ "headers": {
+ "x-twitter-webhooks-signature": "sha256=U7bglX19JitI2xuvyONAc0d/fowIFEeUzkEgnWdGyUM="
+ },
+ "params": {
+ "for_user_id": "123",
+ "tweet_create_events": [
+ {
+ "created_at": "Wed Nov 21 00:13:13 +0000 2018",
+ "id": 1065035365336141825,
+ "id_str": "1065035365336141825",
+ "text": "@znuny Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et… https://t.co/b9woj0QXNZ",
+ "source": "Twitter Web Client",
+ "truncated": true,
+ "in_reply_to_status_id": null,
+ "in_reply_to_status_id_str": null,
+ "in_reply_to_user_id": 123,
+ "in_reply_to_user_id_str": "123",
+ "in_reply_to_screen_name": "znuny",
+ "user": {
+ "id": 219826253,
+ "id_str": "219826253",
+ "name": "Martin Edenhofer",
+ "screen_name": "medenhofer",
+ "location": null,
+ "url": "http://edenhofer.de/",
+ "description": "Open Source professional and geek. Also known as #OTRS and #Zammad inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
+ "translator_type": "regular",
+ "protected": false,
+ "verified": false,
+ "followers_count": 310,
+ "friends_count": 314,
+ "listed_count": 16,
+ "favourites_count": 129,
+ "statuses_count": 225,
+ "created_at": "Fri Nov 26 00:19:49 +0000 2010",
+ "utc_offset": null,
+ "time_zone": null,
+ "geo_enabled": false,
+ "lang": "en",
+ "contributors_enabled": false,
+ "is_translator": false,
+ "profile_background_color": "C0DEED",
+ "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
+ "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
+ "profile_background_tile": true, "profile_link_color": "0084B4", "profile_sidebar_border_color": "FFFFFF",
+ "profile_sidebar_fill_color": "DDEEF6",
+ "profile_text_color": "333333",
+ "profile_use_background_image": true,
+ "profile_image_url": "http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
+ "profile_image_url_https": "https://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
+ "profile_banner_url": "https://pbs.twimg.com/profile_banners/219826253/1349428277",
+ "default_profile": false,
+ "default_profile_image": false,
+ "following": null,
+ "follow_request_sent": null,
+ "notifications": null
+ },
+ "geo": null,
+ "coordinates": null,
+ "place": null,
+ "contributors": null,
+ "is_quote_status": false,
+ "extended_tweet": {
+ "full_text": "@znuny Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lore",
+ "display_text_range": [0, 279],
+ "entities": {
+ "hashtags": [],
+ "urls": [],
+ "user_mentions": [
+ {
+ "screen_name": "znuny",
+ "name": "Znuny / ES for OTRS",
+ "id": 123,
+ "id_str": "123",
+ "indices": [0, 6]
+ }
+ ],
+ "symbols": []
+ }
+ },
+ "quote_count": 0,
+ "reply_count": 0,
+ "retweet_count": 0,
+ "favorite_count": 0,
"entities": {
"hashtags": [],
- "urls": [],
+ "urls": [
+ {
+ "url": "https://t.co/b9woj0QXNZ",
+ "expanded_url": "https://twitter.com/i/web/status/1065035365336141825",
+ "display_url": "twitter.com/i/web/status/1…",
+ "indices": [117, 140]
+ }
+ ],
"user_mentions": [
{
"screen_name": "znuny",
@@ -73,38 +103,13 @@
}
],
"symbols": []
- }
- },
- "quote_count": 0,
- "reply_count": 0,
- "retweet_count": 0,
- "favorite_count": 0,
- "entities": {
- "hashtags": [],
- "urls": [
- {
- "url": "https://t.co/b9woj0QXNZ",
- "expanded_url": "https://twitter.com/i/web/status/1065035365336141825",
- "display_url": "twitter.com/i/web/status/1…",
- "indices": [117, 140]
- }
- ],
- "user_mentions": [
- {
- "screen_name": "znuny",
- "name": "Znuny / ES for OTRS",
- "id": 123,
- "id_str": "123",
- "indices": [0, 6]
- }
- ],
- "symbols": []
- },
- "favorited": false,
- "retweeted": false,
- "filter_level": "low",
- "lang": "ro",
- "timestamp_ms": "1542759193153"
- }
- ]
-}
\ No newline at end of file
+ },
+ "favorited": false,
+ "retweeted": false,
+ "filter_level": "low",
+ "lang": "ro",
+ "timestamp_ms": "1542759193153"
+ }
+ ]
+ }
+}
diff --git a/test/data/twitter/webhook3_direct_message.json b/test/data/twitter/webhook3_direct_message.json
index c441ac674..2fbd141f5 100644
--- a/test/data/twitter/webhook3_direct_message.json
+++ b/test/data/twitter/webhook3_direct_message.json
@@ -1,57 +1,62 @@
{
- "for_user_id": "123",
- "direct_message_events": [
- {
- "type": "message_create",
- "id": "1063077238797725701",
- "created_timestamp": "1542292339406",
- "message_create": {
- "target": {
- "recipient_id": "123"
- },
- "sender_id": "456",
- "message_data": {
- "text": "Hello again!",
- "entities": {
- "hashtags": [],
- "symbols": [],
- "user_mentions": [],
- "urls": []
+ "headers" : {
+ "x-twitter-webhooks-signature" : "sha256=OTguUdchBdxNal/csZsRkytKL5srrUuezZ3hp/2E404="
+ },
+ "params" : {
+ "for_user_id": "123",
+ "direct_message_events": [
+ {
+ "type": "message_create",
+ "id": "1063077238797725701",
+ "created_timestamp": "1542292339406",
+ "message_create": {
+ "target": {
+ "recipient_id": "123"
+ },
+ "sender_id": "456",
+ "message_data": {
+ "text": "Hello again!",
+ "entities": {
+ "hashtags": [],
+ "symbols": [],
+ "user_mentions": [],
+ "urls": []
+ }
}
}
}
- }
- ],
- "users": {
- "456": {
- "id": "456",
- "created_timestamp": "1290730789000",
- "name": "Martin Edenhofer",
- "screen_name": "medenhofer",
- "description": "Open Source professional and geek. Also known as #OTRS and #Zammad inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
- "url": "https://t.co/whm4HTWdMw",
- "protected": false,
- "verified": false,
- "followers_count": 312,
- "friends_count": 314,
- "statuses_count": 222,
- "profile_image_url": "http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
- "profile_image_url_https": "https://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg"
- },
- "123": {
- "id": "123",
- "created_timestamp": "1476091912921",
- "name": "Zammad HQ",
- "screen_name": "zammadhq",
- "description": "Helpdesk and Customer Support made easy. Open Source for download or to go with SaaS. #zammad",
- "url": "https://t.co/XITyrXmhTP",
- "protected": false,
- "verified": false,
- "followers_count": 427,
- "friends_count": 512,
- "statuses_count": 437,
- "profile_image_url": "http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg",
- "profile_image_url_https": "https://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg"
+ ],
+ "users": {
+ "456": {
+ "id": "456",
+ "created_timestamp": "1290730789000",
+ "name": "Martin Edenhofer",
+ "screen_name": "medenhofer",
+ "description": "Open Source professional and geek. Also known as #OTRS and #Zammad inventor. ;)\r\nEntrepreneur and Advisor for open source people in need.",
+ "url": "https://t.co/whm4HTWdMw",
+ "protected": false,
+ "verified": false,
+ "followers_count": 312,
+ "friends_count": 314,
+ "statuses_count": 222,
+ "profile_image_url": "http://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg",
+ "profile_image_url_https": "https://pbs.twimg.com/profile_images/794220000450150401/D-eFg44R_normal.jpg"
+ },
+ "123": {
+ "id": "123",
+ "created_timestamp": "1476091912921",
+ "name": "Zammad HQ",
+ "screen_name": "zammadhq",
+ "description": "Helpdesk and Customer Support made easy. Open Source for download or to go with SaaS. #zammad",
+ "url": "https://t.co/XITyrXmhTP",
+ "protected": false,
+ "verified": false,
+ "followers_count": 427,
+ "friends_count": 512,
+ "statuses_count": 437,
+ "profile_image_url": "http://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg",
+ "profile_image_url_https": "https://pbs.twimg.com/profile_images/785412960797745152/wxdIvejo_normal.jpg"
+ }
}
}
}