Refactored twitter channel backend.

This commit is contained in:
Thorsten Eckel 2015-07-02 17:13:04 +02:00
parent d80ddecc44
commit dc7d821728
6 changed files with 451 additions and 429 deletions

View file

@ -30,32 +30,40 @@ Example:
{ {
"id":1, "id":1,
"area":"Twitter::Inbound", "area":"Twitter::Inbound",
"adapter":"Twitter2", "adapter":"Twitter",
"group_id:": 1, "group_id:": 1,
"options":{ "options":{
"consumer_key":"PJ4c3dYYRtSZZZdOKo8ow", auth: {
"consumer_secret":"ggAdnJE2Al1Vv0cwwvX5bdvKOieFs0vjCIh5M8Dxk", "consumer_key":"PJ4c3dYYRtSZZZdOKo8ow",
"oauth_token":"293437546-xxRa9g74CercnU5AvY1uQwLLGIYrV1ezYtpX8oKW", "consumer_secret":"ggAdnJE2Al1Vv0cwwvX5bdvKOieFs0vjCIh5M8Dxk",
"oauth_token_secret":"ju0E4l9OdY2Lh1iTKMymAu6XVfOaU2oGxmcbIMRZQK4", "oauth_token":"293437546-xxRa9g74CercnU5AvY1uQwLLGIYrV1ezYtpX8oKW",
"search":[ "oauth_token_secret":"ju0E4l9OdY2Lh1iTKMymAu6XVfOaU2oGxmcbIMRZQK4",
{
"item":"#otrs",
"group_id":1,
},
{
"item":"#zombie42",
"group_id":1,
},
{
"item":"#otterhub",
"group_id":1,
}
],
"mentions" {
"group_id":1,
}, },
"direct_messages": { "sync":{
"group_id":1, "search":[
{
"item":"#otrs",
"type": "mixed", # optional, possible 'mixed' (default), 'recent', 'popular'
"group": "OTRS",
"limit": 1, # optional
},
{
"item":"#zombie23",
"group": "Zombie Apocalypse Early Warning System",
},
{
"item":"#otterhub",
"group": "Community",
}
],
"mentions" {
"group": "Twitter",
"limit": 100, # optional
},
"direct_messages": {
"group": "Twitter",
"limit": 1, # optional
}
} }
}, },
"active":true, "active":true,

View file

@ -0,0 +1,100 @@
# Copyright (C) 2012-2015 Zammad Foundation, http://zammad-foundation.org/
class Channel::Twitter
def fetch (channel)
@channel = channel
@tweet = Tweet.new( @channel[:options][:auth] )
@sync = @channel[:options][:sync]
Rails.logger.debug "twitter fetch started"
fetch_search
fetch_mentions
fetch_direct_messages
disconnect
Rails.logger.debug 'twitter fetch completed'
end
def send(article, _notification = false)
@channel = Channel.find_by( area: 'Twitter::Inbound', active: true )
@tweet = Tweet.new( @channel[:options][:auth] )
@sync = @channel[:options][:sync]
tweet = @tweet.from_article(article)
disconnect
tweet
end
def disconnect
@tweet.disconnect
end
private
def fetch_search
return if !@sync[:search]
return if @sync[:search].length == 0
# search results
@sync[:search].each { |search|
result_type = search[:type] || 'mixed'
Rails.logger.debug " - searching for '#{search[:term]}'"
counter = 0
@tweet.client.search( search[:term], result_type: result_type ).collect{ |tweet|
break if search[:limit] && search[:limit] <= counter
break if Ticket::Article.find_by( message_id: tweet.id.to_s )
@tweet.to_group( tweet, search[:group] )
counter += 1
}
}
end
def fetch_mentions
return if !@sync[:mentions]
Rails.logger.debug ' - searching for mentions'
counter = 0
@tweet.client.mentions_timeline.each { |tweet|
break if @sync[:mentions][:limit] && @sync[:mentions][:limit] <= counter
break if Ticket::Article.find_by( message_id: tweet.id.to_s )
@tweet.to_group( tweet, @sync[:mentions][:group] )
counter += 1
}
end
def fetch_direct_messages
return if !@sync[:direct_messages]
Rails.logger.debug ' - searching for direct_messages'
counter = 0
@tweet.client.direct_messages.each { |tweet|
break if @sync[:direct_messages][:limit] && @sync[:direct_messages][:limit] <= counter
break if Ticket::Article.find_by( message_id: tweet.id.to_s )
@tweet.to_group( tweet, @sync[:direct_messages][:group] )
counter += 1
}
end
end

View file

@ -1,303 +0,0 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
require 'twitter'
class Channel::TWITTER2
def connect(channel)
@client = Twitter::REST::Client.new do |config|
config.consumer_key = channel[:options][:consumer_key]
config.consumer_secret = channel[:options][:consumer_secret]
config.access_token = channel[:options][:oauth_token]
config.access_token_secret = channel[:options][:oauth_token_secret]
end
end
def disconnect
return if !@client
@client = nil
end
def fetch (channel)
Rails.logger.info "fetching tweets (oauth_token#{channel[:options][:oauth_token]})"
@client = connect(channel)
# search results
if channel[:options][:search]
channel[:options][:search].each { |search|
Rails.logger.info " - searching for #{search[:item]}"
tweets = []
@client.search( search[:item], count: 50, result_type: 'recent' ).collect do |tweet|
tweets.push tweet
end
@article_type = 'twitter status'
fetch_loop( tweets, channel, search[:group] )
}
end
# mentions
if channel[:options][:mentions]
Rails.logger.info ' - searching for mentions'
tweets = @client.mentions_timeline
@article_type = 'twitter status'
fetch_loop( tweets, channel, channel[:options][:mentions][:group] )
end
# direct messages
if channel[:options][:direct_messages]
Rails.logger.info ' - searching for direct_messages'
tweets = @client.direct_messages
@article_type = 'twitter direct-message'
fetch_loop( tweets, channel, channel[:options][:direct_messages][:group] )
end
Rails.logger.info 'done'
disconnect
end
def fetch_loop( tweets, channel, group )
# get all tweets
all_tweets = []
result_class = tweets.class
if result_class.to_s == 'Array'
all_tweets = tweets
elsif result_class.to_s == 'Twitter::SearchResults'
tweets.results.map do |tweet|
all_tweets.push tweet
end
else
Rails.logger.error 'UNKNOWN: ' + result_class.to_s
end
# find tweets
all_tweets.each do |tweet|
# check if tweet is already imported
article = Ticket::Article.find_by( message_id: tweet.id.to_s )
# check if sender already exists
next if article
# use transaction
ActiveRecord::Base.transaction do
# reset current_user
UserInfo.current_user_id = 1
Rails.logger.info 'import tweet'
fetch_import( tweet, channel, group )
end
# execute ticket events
Observer::Ticket::Notification.transaction
end
end
def fetch_import(tweet, channel, group)
# do sender lockup if needed
sender = nil
# status (full user data is included)
if tweet.respond_to?('user')
sender = tweet.user
# direct message (full user data is included)
elsif tweet.respond_to?('sender')
sender = tweet.sender
# search (no user data is included, do extra lookup)
elsif tweet.respond_to?('from_user_id')
begin
sender = @client.user(tweet.from_user_id)
rescue => e
Rails.logger.error 'Exception: twitter: ' + e.inspect
return
end
end
# check if parent exists
user = nil, ticket = nil, article = nil
if tweet.respond_to?('in_reply_to_status_id') && tweet.in_reply_to_status_id && tweet.in_reply_to_status_id.to_s != ''
Rails.logger.info 'import in_reply_tweet ' + tweet.in_reply_to_status_id.to_s
tweet_sub = @client.status( tweet.in_reply_to_status_id )
#Rails.logger.debug tweet_sub.inspect
(user, ticket, article) = fetch_import(tweet_sub, channel, group)
end
# create stuff
user = fetch_user_create(tweet, sender)
if !ticket
Rails.logger.info 'create new ticket...'
ticket = fetch_ticket_create(user, tweet, sender, channel, group)
end
article = fetch_article_create(user, ticket, tweet, sender)
[user, ticket, article]
end
def fetch_user_create(_tweet, sender)
# create sender in db
# puts tweet.inspect
# user = User.where( :login => tweet.sender.screen_name ).first
auth = Authorization.find_by( uid: sender.id, provider: 'twitter' )
user = nil
if auth
Rails.logger.info 'user_id', auth.user_id
user = User.find_by( id: auth.user_id )
end
if !user
Rails.logger.info 'create user...'
roles = Role.where( name: 'Customer' )
user = User.create(
login: sender.screen_name,
firstname: sender.name,
lastname: '',
email: '',
password: '',
image_source: sender.profile_image_url.to_s,
note: sender.description,
active: true,
roles: roles,
updated_by_id: 1,
created_by_id: 1
)
Rails.logger.info 'autentication create...'
authentication = Authorization.create(
uid: sender.id,
username: sender.screen_name,
user_id: user.id,
provider: 'twitter'
)
else
Rails.logger.info 'user exists'
end
# set current user
UserInfo.current_user_id = user.id
user
end
def fetch_ticket_create(user, tweet, _sender, _channel, group)
#Rails.logger.info '+++++++++++++++++++++++++++' + tweet.inspect
# check if ticket exists
if tweet.respond_to?('in_reply_to_status_id') && tweet.in_reply_to_status_id && tweet.in_reply_to_status_id.to_s != ''
Rails.logger.info 'tweet.in_reply_to_status_id found: ' + tweet.in_reply_to_status_id.to_s
article = Ticket::Article.find_by( message_id: tweet.in_reply_to_status_id.to_s )
if article
Rails.logger.info 'article with id found tweet.in_reply_to_status_id found: ' + tweet.in_reply_to_status_id.to_s
return article.ticket
end
end
# find if record already exists
article = Ticket::Article.find_by( message_id: tweet.id.to_s )
if article
return article.ticket
end
ticket = nil
if @article_type == 'twitter direct-message'
ticket = Ticket.find_by( customer_id: user.id )
if ticket
state_type = Ticket::StateType.where( ticket.state.state_type_id )
if state_type.name == 'closed' || state_type.name == 'closed'
ticket = nil
end
end
end
if !ticket
group = Group.find_by( name: group )
group_id = 1
if group
group_id = group.id
end
state = Ticket::State.find_by( name: 'new' )
state_id = 1
if state
state_id = state.id
end
priority = Ticket::Priority.find_by( name: '2 normal' )
priority_id = 1
if priority
priority_id = priority.id
end
ticket = Ticket.create(
group_id: group_id,
customer_id: user.id,
title: tweet.text[0, 40],
state_id: state_id,
priority_id: priority_id,
)
end
ticket
end
def fetch_article_create( _user, ticket, tweet, sender )
# find if record already exists
article = Ticket::Article.find_by( message_id: tweet.id.to_s )
return article if article
# set ticket state to open if not new
if ticket.state.name != 'new'
ticket.state = Ticket::State.find_by( name: 'open' )
ticket.save
end
# import tweet
to = nil
if tweet.respond_to?('recipient')
to = tweet.recipient.name
end
article = Ticket::Article.create(
ticket_id: ticket.id,
type_id: Ticket::Article::Type.find_by( name: @article_type ).id,
sender_id: Ticket::Article::Sender.find_by( name: 'Customer' ).id,
body: tweet.text,
from: sender.name,
to: to,
message_id: tweet.id,
internal: false,
)
end
def send(attr, _notification = false)
# Rails.logger.debug('tweeeeettttt!!!!!!')
channel = Channel.find_by( area: 'Twitter::Inbound', active: true )
client = Twitter::REST::Client.new do |config|
config.consumer_key = channel[:options][:consumer_key]
config.consumer_secret = channel[:options][:consumer_secret]
config.access_token = channel[:options][:oauth_token]
config.access_token_secret = channel[:options][:oauth_token_secret]
end
if attr[:type] == 'twitter direct-message'
Rails.logger.info 'to:' + attr[:to].to_s
dm = client.create_direct_message(
attr[:to].to_s,
attr[:body].to_s,
{}
)
# Rails.logger.info dm.inspect
return dm
end
return if attr[:type] != 'twitter status'
message = client.update(
attr[:body].to_s,
{
in_reply_to_status_id: attr[:in_reply_to]
}
)
# Rails.logger.debug message.inspect
message
end
end

View file

@ -1,5 +1,8 @@
# Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/ # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
# http://stem.ps/rails/2015/01/25/ruby-gotcha-toplevel-constant-referenced-by.html
require 'channel/twitter'
class Observer::Ticket::Article::CommunicateTwitter < ActiveRecord::Observer class Observer::Ticket::Article::CommunicateTwitter < ActiveRecord::Observer
observe 'ticket::_article' observe 'ticket::_article'
@ -10,24 +13,21 @@ class Observer::Ticket::Article::CommunicateTwitter < ActiveRecord::Observer
# if sender is customer, do not communication # if sender is customer, do not communication
sender = Ticket::Article::Sender.lookup( id: record.sender_id ) sender = Ticket::Article::Sender.lookup( id: record.sender_id )
return 1 if sender.nil? return if sender.nil?
return 1 if sender['name'] == 'Customer' return if sender['name'] == 'Customer'
# only apply on tweets # only apply on tweets
type = Ticket::Article::Type.lookup( id: record.type_id ) type = Ticket::Article::Type.lookup( id: record.type_id )
return if type['name'] != 'twitter direct-message' && type['name'] != 'twitter status' return if type['name'] !~ /\Atwitter/
a = Channel::TWITTER2.new twitter = Channel::Twitter.new
message = a.send( tweet = twitter.send({
{ type: type['name'],
type: type['name'], to: record.to,
to: record.to, body: record.body,
body: record.body, in_reply_to: record.in_reply_to
in_reply_to: record.in_reply_to })
}, record.message_id = tweet.id
#Rails.application.config.channel_twitter
)
record.message_id = message.id
record.save record.save
end end
end end

226
lib/tweet.rb Normal file
View file

@ -0,0 +1,226 @@
# Copyright (C) 2012-2015 Zammad Foundation, http://zammad-foundation.org/
require 'twitter'
class Tweet
attr_accessor :client
def initialize(auth)
@client = Twitter::REST::Client.new do |config|
config.consumer_key = auth[:consumer_key]
config.consumer_secret = auth[:consumer_secret]
config.access_token = auth[:oauth_token]
config.access_token_secret = auth[:oauth_token_secret]
end
end
def disconnect
return if !@client
@client = nil
end
def user(tweet)
# status (full user data is included)
return tweet.user if tweet.respond_to?('user')
# direct message (full user data is included)
return tweet.sender if tweet.respond_to?('sender')
# search (no user data is included, do extra lookup)
begin
return @client.user(tweet.from_user_id) if tweet.respond_to?('from_user_id')
rescue => e
Rails.logger.error "Twitter (#{tweet.id}): 'from_user_id' lookup error '#{e.inspect}'"
end
Rails.logger.error "Twitter (#{tweet.id}): unknown user source"
return
end
def to_user(tweet)
Rails.logger.debug "Create user from tweet..."
Rails.logger.debug tweet.inspect
# do tweet_user lookup
tweet_user = user(tweet)
return if !tweet_user
auth = Authorization.find_by( uid: tweet_user.id, provider: 'twitter' )
# create or update user
user_data = {
login: tweet_user.screen_name,
firstname: tweet_user.name,
lastname: '',
email: '',
password: '',
image_source: tweet_user.profile_image_url.to_s,
note: tweet_user.description,
active: true,
roles: Role.where( name: 'Customer' ),
}
if auth
user_data[:id] = auth.user_id
end
user = User.create_or_update( user_data )
# create or update authorization
auth_data = {
uid: tweet_user.id,
username: tweet_user.screen_name,
user_id: user.id,
provider: 'twitter'
}
if auth
auth.update_attributes( auth_data )
else
Authorization.new( auth_data )
end
UserInfo.current_user_id = user.id
user
end
def to_ticket(tweet, user, group)
Rails.logger.debug "Create ticket from tweet..."
Rails.logger.debug tweet.inspect
Rails.logger.debug user.inspect
Rails.logger.debug group.inspect
if tweet.class.to_s == 'Twitter::DirectMessage'
ticket = Ticket.find_by(
customer_id: user.id,
state: Ticket::State.where(
state_type_id: Ticket::StateType.where(
name: 'closed',
)
)
)
return ticket if ticket
end
Ticket.create(
customer_id: user.id,
title: "#{tweet.text[0, 37]}...",
group: Group.find_by( name: group ),
state: Ticket::State.find_by( name: 'new' ),
priority: Ticket::Priority.find_by( name: '2 normal' ),
)
end
def to_article(tweet, user, ticket)
Rails.logger.debug "Create article from tweet..."
Rails.logger.debug tweet.inspect
Rails.logger.debug user.inspect
Rails.logger.debug ticket.inspect
# set ticket state to open if not new
if ticket.state.name != 'new'
ticket.state = Ticket::State.find_by( name: 'open' )
ticket.save
end
# import tweet
to = nil
if tweet.respond_to?('recipient')
to = tweet.recipient.name
end
article_type = 'twitter status'
if tweet.class.to_s == 'Twitter::DirectMessage'
article_type = 'twitter direct-message'
end
Ticket::Article.create(
from: user.login,
to: to,
body: tweet.text,
message_id: tweet.id,
ticket_id: ticket.id,
type: Ticket::Article::Type.find_by( name: article_type ),
sender: Ticket::Article::Sender.find_by( name: 'Customer' ),
internal: false,
)
end
def to_group(tweet, group)
Rails.logger.debug 'import tweet'
ticket = nil
# use transaction
ActiveRecord::Base.transaction do
UserInfo.current_user_id = 1
# check if parent exists
user = to_user(tweet)
return if !user
if tweet.respond_to?('in_reply_to_status_id') && tweet.in_reply_to_status_id && tweet.in_reply_to_status_id.to_s != ''
existing_article = Ticket::Article.find_by( message_id: tweet.in_reply_to_status_id.to_s )
if existing_article
ticket = existing_article.ticket
else
Rails.logger.debug 'import in_reply_tweet ' + tweet.in_reply_to_status_id.to_s
parent_tweet = @client.status( tweet.in_reply_to_status_id )
ticket = to_group( parent_tweet, group )
end
else
ticket = to_ticket(tweet, user, group)
end
to_article(tweet, user, ticket)
# execute ticket events
Observer::Ticket::Notification.transaction
end
ticket
end
def from_article(article)
tweet = nil
if article[:type] == 'twitter direct-message'
Rails.logger.debug "Create twitter direct message from article to '#{article[:to]}'..."
tweet = @client.create_direct_message(
article[:to],
article[:body],
{}
)
elsif article[:type] == 'twitter status'
Rails.logger.debug "Create tweet from article..."
tweet = @client.update(
article[:body],
{
in_reply_to_status_id: article[:in_reply_to]
}
)
end
Rails.logger.debug tweet.inspect
tweet
end
end

View file

@ -20,40 +20,44 @@ class TwitterTest < ActiveSupport::TestCase
consumer_key = 'd2zoZBmMXmT7KLPgEHSzpw' consumer_key = 'd2zoZBmMXmT7KLPgEHSzpw'
consumer_secret = 'QMUrlyDlqjITCkWdrOgsTxMVVLxr4A4IW3DIgtIg' consumer_secret = 'QMUrlyDlqjITCkWdrOgsTxMVVLxr4A4IW3DIgtIg'
# user1: armin_theo (is system and is following marion_bauer) # armin_theo (is system and is following marion_bauer)
user1_token = '1405469528-WQ6XHizgrbYasUwjp0I0TUONhftNkrfrpgFLrdc' armin_theo_token = '1405469528-WQ6XHizgrbYasUwjp0I0TUONhftNkrfrpgFLrdc'
user1_token_secret = '0LHChGFlQx9jSxM8tkBsuDOMhbJMSXTL2zKJJO5Xk' armin_theo_token_secret = '0LHChGFlQx9jSxM8tkBsuDOMhbJMSXTL2zKJJO5Xk'
# user2: me_bauer (is following armin_theo) # me_bauer (is following armin_theo)
user2_token = '1406098795-XQTjg1Zj5uVW0C11NNpNA4xopyclRJJoriWis0I' me_bauer_token = '1406098795-XQTjg1Zj5uVW0C11NNpNA4xopyclRJJoriWis0I'
user2_token_secret = 'T8ph5afeSDjGDA9X1ZBlzEvoSiXfN266ZZUMj5UaY' me_bauer_token_secret = 'T8ph5afeSDjGDA9X1ZBlzEvoSiXfN266ZZUMj5UaY'
# add channel # add channel
current = Channel.where( adapter: 'Twitter2' ) current = Channel.where( adapter: 'Twitter' )
current.each(&:destroy) current.each(&:destroy)
Channel.create( Channel.create(
adapter: 'Twitter2', adapter: 'Twitter',
area: 'Twitter::Inbound', area: 'Twitter::Inbound',
options: { options: {
consumer_key: consumer_key, auth: {
consumer_secret: consumer_secret, consumer_key: consumer_key,
oauth_token: user1_token, consumer_secret: consumer_secret,
oauth_token_secret: user1_token_secret, oauth_token: armin_theo_token,
search: [ oauth_token_secret: armin_theo_token_secret,
{ },
item: '#citheo42', sync: {
search: [
{
term: '#citheo42',
group: 'Twitter',
},
{
term: '#citheo24',
group: 'Users',
},
],
mentions: {
group: 'Twitter', group: 'Twitter',
}, },
{ direct_messages: {
item: '#citheo24', group: 'Twitter',
group: 'Users', }
},
],
mentions: {
group: 'Twitter',
},
direct_messages: {
group: 'Twitter',
} }
}, },
active: true, active: true,
@ -63,51 +67,49 @@ class TwitterTest < ActiveSupport::TestCase
test 'new outbound and reply' do test 'new outbound and reply' do
user = User.find(2) hash = '#citheo42' + rand(9999).to_s
group = Group.where( name: 'Twitter' ).first user = User.find(2)
state = Ticket::State.where( name: 'new' ).first text = "Today the weather is really nice... #{hash}"
priority = Ticket::Priority.where( name: '2 normal' ).first
hash = '#citheo42' + rand(9999).to_s
text = 'Today the weather is really nice... ' + hash
ticket = Ticket.create( ticket = Ticket.create(
group_id: group.id, title: text[0, 40],
customer_id: user.id, customer_id: user.id,
title: text[0, 40], group: Group.find_by( name: 'Twitter' ),
state_id: state.id, state: Ticket::State.find_by( name: 'new' ),
priority_id: priority.id, priority: Ticket::Priority.find_by( name: '2 normal' ),
updated_by_id: 1, updated_by_id: 1,
created_by_id: 1, created_by_id: 1,
) )
assert( ticket, 'outbound ticket created' ) assert( ticket, "outbound ticket created, text: #{text}" )
article = Ticket::Article.create( article = Ticket::Article.create(
ticket_id: ticket.id, ticket_id: ticket.id,
type_id: Ticket::Article::Type.where( name: 'twitter status' ).first.id, body: text,
sender_id: Ticket::Article::Sender.where( name: 'Agent' ).first.id, type: Ticket::Article::Type.find_by( name: 'twitter status' ),
body: text, sender: Ticket::Article::Sender.find_by( name: 'Agent' ),
#:from => sender.name, internal: false,
#:to => to,
#:message_id => tweet.id,
internal: false,
updated_by_id: 1, updated_by_id: 1,
created_by_id: 1, created_by_id: 1,
) )
assert( article, 'outbound article created' ) assert( article, "outbound article created, text: #{text}" )
assert_equal( article.ticket.articles.count, 1 )
sleep 10
# reply by me_bauer # reply by me_bauer
client = Twitter::REST::Client.new do |config| client = Twitter::REST::Client.new do |config|
config.consumer_key = consumer_key config.consumer_key = consumer_key
config.consumer_secret = consumer_secret config.consumer_secret = consumer_secret
config.access_token = user2_token config.access_token = me_bauer_token
config.access_token_secret = user2_token_secret config.access_token_secret = me_bauer_token_secret
end
client.search(hash, count: 50, result_type: 'recent').collect do |tweet|
assert_equal( tweet.id, article.message_id )
end end
reply_hash = '#weather' + rand(9999).to_s tweet_found = false
reply_text = '@armin_theo on my side the weather is also nice! 😍😍😍 ' + reply_hash client.user_timeline('armin_theo').each { |tweet|
next if tweet.id != article.message_id
tweet_found = true
break
}
assert( tweet_found, "found outbound '#{text}' tweet '#{article.message_id}'" )
reply_text = '@armin_theo on my side the weather is nice, too! 😍😍😍 #weather' + rand(9999).to_s
tweet = client.update( tweet = client.update(
reply_text, reply_text,
{ {
@ -115,43 +117,40 @@ class TwitterTest < ActiveSupport::TestCase
} }
) )
sleep 10
# fetch check system account # fetch check system account
Channel.fetch Channel.fetch
# check if follow up article has been created # check if follow up article has been created
assert_equal( article.ticket.articles.count, 2 ) article = Ticket::Article.find_by( message_id: tweet.id )
reply_article = article.ticket.articles.last
assert_equal( reply_article.body, reply_text.utf8_to_3bytesutf8 )
assert( article, "article tweet '#{tweet.id}' imported" )
assert_equal( 2, article.ticket.articles.count, 'ticket article inbound count' )
assert_equal( reply_text.utf8_to_3bytesutf8, ticket.articles.last.body, 'ticket article inbound body' )
end end
test 'new by direct message inbound' do test 'new by direct message inbound' do
# cleanup direct messages of system # cleanup direct messages of system
client = Twitter::REST::Client.new do |config| client = Twitter::REST::Client.new do |config|
config.consumer_key = consumer_key config.consumer_key = consumer_key
config.consumer_secret = consumer_secret config.consumer_secret = consumer_secret
config.access_token = user1_token config.access_token = armin_theo_token
config.access_token_secret = user1_token_secret config.access_token_secret = armin_theo_token_secret
end end
dms = client.direct_messages( count: 200 ) dms = client.direct_messages( count: 200 )
dms.each {|dm| dms.each {|dm|
client.destroy_direct_message(dm.id) client.destroy_direct_message(dm.id)
} }
# direct message to @armin_theo
client = Twitter::REST::Client.new( client = Twitter::REST::Client.new(
consumer_key: consumer_key, consumer_key: consumer_key,
consumer_secret: consumer_secret, consumer_secret: consumer_secret,
access_token: user2_token, access_token: me_bauer_token,
access_token_secret: user2_token_secret access_token_secret: me_bauer_token_secret
) )
dms = client.direct_messages( count: 200 ) dms = client.direct_messages( count: 200 )
dms.each {|dm| dms.each {|dm|
client.destroy_direct_message(dm.id) client.destroy_direct_message(dm.id)
} }
sleep 10
hash = '#citheo44' + rand(9999).to_s hash = '#citheo44' + rand(9999).to_s
text = 'How about the details? ' + hash text = 'How about the details? ' + hash
@ -164,43 +163,35 @@ class TwitterTest < ActiveSupport::TestCase
# fetch check system account # fetch check system account
article = nil article = nil
(1..4).each { (1..4).each {
next if article
sleep 25
Channel.fetch Channel.fetch
# check if ticket and article has been created # check if ticket and article has been created
article = Ticket::Article.where( message_id: dm.id ).last article = Ticket::Article.find_by( message_id: dm.id )
break if article
sleep 5
} }
puts '----------------------------------------'
puts 'DM: ' + dm.inspect
puts 'AT: ' + article.inspect
puts '----------------------------------------'
assert( article, 'inbound article created' ) assert( article, 'inbound article created' )
#ticket = Ticket.find( article.ticket.id )
ticket = article.ticket ticket = article.ticket
assert( ticket, 'ticket of inbound article exists' ) assert( ticket, 'ticket of inbound article exists' )
assert( ticket.articles, 'ticket.articles exists' ) assert( ticket.articles, 'ticket.articles exists' )
article_count = ticket.articles.count assert_equal( ticket.articles.count, 1, 'ticket article inbound count' )
assert( article_count ) assert_equal( ticket.state.name, 'new' )
#assert_equal( ticket.state.name, 'new' )
# reply via ticket # reply via ticket
outbound_article = Ticket::Article.create( outbound_article = Ticket::Article.create(
ticket_id: ticket.id, ticket_id: ticket.id,
type_id: Ticket::Article::Type.where( name: 'twitter direct-message' ).first.id, to: 'me_bauer',
sender_id: Ticket::Article::Sender.where( name: 'Agent' ).first.id, body: text,
body: text, type: Ticket::Article::Type.find_by( name: 'twitter direct-message' ),
#:from => sender.name, sender: Ticket::Article::Sender.find_by( name: 'Agent' ),
to: 'me_bauer', internal: false,
internal: false,
updated_by_id: 1, updated_by_id: 1,
created_by_id: 1, created_by_id: 1,
) )
assert( outbound_article, 'outbound article created' ) assert( outbound_article, 'outbound article created' )
assert_equal( outbound_article.ticket.articles.count, article_count + 1 ) assert_equal( outbound_article.ticket.articles.count, 2, 'ticket article outbound count' )
sleep 10
end end
end end