2015-12-17 11:49:40 +00:00
class ExternalCredential :: Twitter
def self . app_verify ( params )
2018-12-03 14:10:36 +00:00
register_webhook ( params )
2015-12-17 11:49:40 +00:00
end
2018-12-03 14:10:36 +00:00
def self . request_account_to_link ( credentials = { } , app_required = true )
2015-12-17 11:49:40 +00:00
external_credential = ExternalCredential . find_by ( name : 'twitter' )
2018-12-03 14:10:36 +00:00
raise Exceptions :: UnprocessableEntity , 'No twitter app configured!' if ! external_credential && app_required
2018-10-09 06:17:41 +00:00
2018-12-03 14:10:36 +00:00
if external_credential
if credentials [ :consumer_key ] . blank?
credentials [ :consumer_key ] = external_credential . credentials [ 'consumer_key' ]
end
if credentials [ :consumer_secret ] . blank?
credentials [ :consumer_secret ] = external_credential . credentials [ 'consumer_secret' ]
end
2015-12-21 00:48:49 +00:00
end
2018-12-03 14:10:36 +00:00
raise Exceptions :: UnprocessableEntity , 'No consumer_key param!' if credentials [ :consumer_key ] . blank?
raise Exceptions :: UnprocessableEntity , 'No consumer_secret param!' if credentials [ :consumer_secret ] . blank?
2015-12-17 11:49:40 +00:00
consumer = OAuth :: Consumer . new (
2015-12-21 00:48:49 +00:00
credentials [ :consumer_key ] ,
credentials [ :consumer_secret ] , {
2015-12-17 11:49:40 +00:00
site : 'https://api.twitter.com'
2015-12-30 13:24:13 +00:00
}
)
2018-12-03 14:10:36 +00:00
begin
request_token = consumer . get_request_token ( oauth_callback : ExternalCredential . callback_url ( 'twitter' ) )
rescue = > e
2020-03-20 10:29:50 +00:00
case e . message
when '401 Authorization Required'
raise " #{ e . message } (Invalid credentials may be to blame.) "
when '403 Forbidden'
raise " #{ e . message } (Your app's callback URL configuration on developer.twitter.com may be to blame.) "
else
raise
2018-12-03 14:10:36 +00:00
end
end
2015-12-17 11:49:40 +00:00
{
request_token : request_token ,
authorize_url : request_token . authorize_url ,
}
end
def self . link_account ( request_token , params )
external_credential = ExternalCredential . find_by ( name : 'twitter' )
2018-12-03 14:10:36 +00:00
raise Exceptions :: UnprocessableEntity , 'No twitter app configured!' if ! external_credential
raise Exceptions :: UnprocessableEntity , 'No request_token for session found!' if ! request_token
raise Exceptions :: UnprocessableEntity , 'Invalid oauth_token given!' if request_token . params [ :oauth_token ] != params [ :oauth_token ]
2015-12-17 11:49:40 +00:00
access_token = request_token . get_access_token ( oauth_verifier : params [ :oauth_verifier ] )
2018-12-03 14:10:36 +00:00
client = TwitterSync . new (
2018-12-19 17:31:51 +00:00
consumer_key : external_credential . credentials [ :consumer_key ] ,
consumer_secret : external_credential . credentials [ :consumer_secret ] ,
access_token : access_token . token ,
2015-12-17 11:49:40 +00:00
access_token_secret : access_token . secret ,
)
2018-12-03 14:10:36 +00:00
client_user = client . who_am_i
2015-12-17 11:49:40 +00:00
2015-12-30 13:24:13 +00:00
# check if account already exists
2017-10-01 12:25:52 +00:00
Channel . where ( area : 'Twitter::Account' ) . each do | channel |
2015-12-30 13:24:13 +00:00
next if ! channel . options
next if ! channel . options [ 'user' ]
next if ! channel . options [ 'user' ] [ 'id' ]
2019-11-07 06:21:46 +00:00
next if channel . options [ 'user' ] [ 'id' ] . to_s != client_user . id . to_s && channel . options [ 'user' ] [ 'screen_name' ] != client_user . screen_name
2018-12-03 14:10:36 +00:00
2019-11-07 06:21:46 +00:00
channel . options [ 'user' ] [ 'id' ] = client_user . id . to_s
2018-12-03 14:10:36 +00:00
channel . options [ 'user' ] [ 'screen_name' ] = client_user . screen_name
channel . options [ 'user' ] [ 'name' ] = client_user . name
2015-12-30 13:24:13 +00:00
# update access_token
channel . options [ 'auth' ] [ 'external_credential_id' ] = external_credential . id
channel . options [ 'auth' ] [ 'oauth_token' ] = access_token . token
channel . options [ 'auth' ] [ 'oauth_token_secret' ] = access_token . secret
2018-12-03 14:10:36 +00:00
channel . save!
subscribe_webhook (
channel : channel ,
client : client ,
external_credential : external_credential ,
)
2015-12-30 13:24:13 +00:00
return channel
2017-10-01 12:25:52 +00:00
end
2015-12-30 13:24:13 +00:00
2015-12-17 11:49:40 +00:00
# create channel
2018-12-03 14:10:36 +00:00
channel = Channel . create! (
2018-12-19 17:31:51 +00:00
area : 'Twitter::Account' ,
options : {
2015-12-17 11:49:40 +00:00
adapter : 'twitter' ,
2018-12-19 17:31:51 +00:00
user : {
2019-11-07 06:21:46 +00:00
id : client_user . id . to_s ,
2018-12-03 14:10:36 +00:00
screen_name : client_user . screen_name ,
2018-12-19 17:31:51 +00:00
name : client_user . name ,
2015-12-17 11:49:40 +00:00
} ,
2018-12-19 17:31:51 +00:00
auth : {
2015-12-17 11:49:40 +00:00
external_credential_id : external_credential . id ,
oauth_token : access_token . token ,
oauth_token_secret : access_token . secret ,
} ,
2018-12-19 17:31:51 +00:00
sync : {
limit : 20 ,
search : [ ] ,
mentions : { } ,
2017-01-19 15:23:41 +00:00
direct_messages : { } ,
2018-12-19 17:31:51 +00:00
track_retweets : false
2015-12-17 11:49:40 +00:00
}
} ,
2018-12-19 17:31:51 +00:00
active : true ,
2015-12-17 11:49:40 +00:00
created_by_id : 1 ,
updated_by_id : 1 ,
)
2018-12-03 14:10:36 +00:00
subscribe_webhook (
channel : channel ,
client : client ,
external_credential : external_credential ,
)
channel
end
def self . webhook_url
" #{ Setting . get ( 'http_type' ) } :// #{ Setting . get ( 'fqdn' ) } #{ Rails . configuration . api_path } /channels_twitter_webhook "
end
def self . register_webhook ( params )
request_account_to_link ( params , false )
raise Exceptions :: UnprocessableEntity , 'No consumer_key param!' if params [ :consumer_key ] . blank?
raise Exceptions :: UnprocessableEntity , 'No consumer_secret param!' if params [ :consumer_secret ] . blank?
raise Exceptions :: UnprocessableEntity , 'No oauth_token param!' if params [ :oauth_token ] . blank?
raise Exceptions :: UnprocessableEntity , 'No oauth_token_secret param!' if params [ :oauth_token_secret ] . blank?
return if params [ :env ] . blank?
env_name = params [ :env ]
client = TwitterSync . new (
2018-12-19 17:31:51 +00:00
consumer_key : params [ :consumer_key ] ,
consumer_secret : params [ :consumer_secret ] ,
access_token : params [ :oauth_token ] ,
2018-12-03 14:10:36 +00:00
access_token_secret : params [ :oauth_token_secret ] ,
)
# needed for verify callback
Cache . write ( 'external_credential_twitter' , {
2018-12-19 17:31:51 +00:00
consumer_key : params [ :consumer_key ] ,
consumer_secret : params [ :consumer_secret ] ,
access_token : params [ :oauth_token ] ,
2018-12-03 14:10:36 +00:00
access_token_secret : params [ :oauth_token_secret ] ,
} )
# verify if webhook is already registered
begin
webhooks = client . webhooks_by_env_name ( env_name )
2019-06-28 11:38:49 +00:00
rescue
2018-12-03 14:10:36 +00:00
begin
webhooks = client . webhooks
raise " Unable to get list of webooks. You use the wrong 'Dev environment label', only #{ webhooks . inspect } available. "
rescue = > e
raise " Unable to get list of webooks. Maybe you do not have an Twitter developer approval right now or you use the wrong 'Dev environment label': #{ e . message } "
end
end
webhook_id = nil
webhook_valid = nil
webhooks . each do | webhook |
next if webhook [ :url ] != webhook_url
webhook_id = webhook [ :id ]
webhook_valid = webhook [ :valid ]
end
# if webhook is already registered
# - in case if webhook is invalid, just send a new verification request
# - in case if webhook is valid return
if webhook_id
if webhook_valid == false
client . webhook_request_verification ( webhook_id , env_name , webhook_url )
end
params [ :webhook_id ] = webhook_id
return params
end
# delete already registered webhooks
webhooks . each do | webhook |
2019-09-03 18:23:29 +00:00
client . webhook_delete ( webhook [ :id ] , env_name )
2018-12-03 14:10:36 +00:00
end
# register new webhook
response = client . webhook_register ( env_name , webhook_url )
params [ :webhook_id ] = response [ :id ]
params
end
def self . subscribe_webhook ( channel : , client : , external_credential : )
env_name = external_credential . credentials [ :env ]
webhook_id = external_credential . credentials [ :webhook_id ]
Rails . logger . debug { " Starting Twitter subscription for webhook_id #{ webhook_id } and Channel #{ channel . id } " }
client . webhook_subscribe ( env_name )
channel . options [ 'subscribed_to_webhook_id' ] = webhook_id
channel . save!
true
2015-12-17 11:49:40 +00:00
end
end