twitter.rb 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. # Copyright (C) 2012-2015 Zammad Foundation, http://zammad-foundation.org/
  2. =begin
  3. fetch tweets from twitter account
  4. options = {
  5. adapter: 'twitter',
  6. auth: {
  7. consumer_key: consumer_key,
  8. consumer_secret: consumer_secret,
  9. oauth_token: armin_theo_token,
  10. oauth_token_secret: armin_theo_token_secret,
  11. },
  12. sync: {
  13. search: [
  14. {
  15. term: '#citheo42',
  16. group_id: 2,
  17. },
  18. {
  19. term: '#citheo24',
  20. group_id: 1,
  21. },
  22. ],
  23. mentions: {
  24. group_id: 2,
  25. },
  26. direct_messages: {
  27. group_id: 2,
  28. }
  29. }
  30. }
  31. instance = Channel::Driver::Twitter.new
  32. result = instance.fetch(options, channel)
  33. returns
  34. {
  35. result: 'ok',
  36. }
  37. =end
  38. class Channel::Driver::Twitter
  39. def fetch (options, channel)
  40. options = check_external_credential(options)
  41. # only fetch once a hour
  42. if Rails.env.production? || Rails.env.development?
  43. if channel.preferences && channel.preferences[:last_fetch] && channel.preferences[:last_fetch] > Time.zone.now - 1.hour
  44. return {
  45. result: 'ok',
  46. notice: '',
  47. }
  48. end
  49. end
  50. @rest_client = TweetRest.new(options[:auth])
  51. @sync = options[:sync]
  52. @channel = channel
  53. Rails.logger.debug 'twitter fetch started'
  54. fetch_mentions
  55. fetch_search
  56. fetch_direct_messages
  57. disconnect
  58. Rails.logger.debug 'twitter fetch completed'
  59. {
  60. result: 'ok',
  61. notice: '',
  62. }
  63. end
  64. =begin
  65. instance = Channel::Driver::Twitter.new
  66. instance.send(
  67. {
  68. adapter: 'twitter',
  69. auth: {
  70. consumer_key: consumer_key,
  71. consumer_secret: consumer_secret,
  72. oauth_token: armin_theo_token,
  73. oauth_token_secret: armin_theo_token_secret,
  74. },
  75. },
  76. twitter_attributes,
  77. notification
  78. )
  79. =end
  80. def send(options, article, _notification = false)
  81. # return if we run import mode
  82. return if Setting.get('import_mode')
  83. options = check_external_credential(options)
  84. @rest_client = TweetRest.new(options[:auth])
  85. tweet = @rest_client.from_article(article)
  86. disconnect
  87. tweet
  88. end
  89. def disconnect
  90. @stream_client.disconnect if @stream_client
  91. @rest_client.disconnect if @rest_client
  92. end
  93. =begin
  94. create stream endpoint form twitter account
  95. options = {
  96. adapter: 'twitter',
  97. auth: {
  98. consumer_key: consumer_key,
  99. consumer_secret: consumer_secret,
  100. oauth_token: armin_theo_token,
  101. oauth_token_secret: armin_theo_token_secret,
  102. },
  103. sync: {
  104. search: [
  105. {
  106. term: '#citheo42',
  107. group_id: 2,
  108. },
  109. {
  110. term: '#citheo24',
  111. group_id: 1,
  112. },
  113. ],
  114. mentions: {
  115. group_id: 2,
  116. },
  117. direct_messages: {
  118. group_id: 2,
  119. }
  120. }
  121. }
  122. instance = Channel::Driver::Twitter.new
  123. stream_instance = instance.stream_instance(channel)
  124. returns
  125. instance_of_stream_handle
  126. =end
  127. def stream_instance(channel)
  128. @channel = channel
  129. options = @channel.options
  130. @stream_client = TweetStream.new(options[:auth])
  131. end
  132. =begin
  133. stream tweets from twitter account
  134. stream_instance.stream
  135. returns
  136. # endless loop
  137. =end
  138. def stream
  139. hashtags = []
  140. @channel.options['sync']['search'].each {|item|
  141. hashtags.push item['term']
  142. }
  143. filter = {
  144. track: hashtags.join(','),
  145. }
  146. if @channel.options['sync']['mentions']['group_id'] != ''
  147. filter[:replies] = 'all'
  148. end
  149. @stream_client.client.user(filter) do |tweet|
  150. next if tweet.class != Twitter::Tweet && tweet.class != Twitter::DirectMessage
  151. next if Ticket::Article.find_by(message_id: tweet.id)
  152. # check direct message
  153. if tweet.class == Twitter::DirectMessage
  154. if @channel.options['sync']['direct_messages']['group_id'] != ''
  155. next if @stream_client.direct_message_limit_reached(tweet)
  156. @stream_client.to_group(tweet, @channel.options['sync']['direct_messages']['group_id'], @channel)
  157. end
  158. next
  159. end
  160. next if @stream_client.tweet_limit_reached(tweet)
  161. # check if it's mention
  162. if @channel.options['sync']['mentions']['group_id'] != ''
  163. hit = false
  164. if tweet.user_mentions
  165. tweet.user_mentions.each {|user|
  166. if user.id.to_s == @channel.options['user']['id'].to_s
  167. hit = true
  168. end
  169. }
  170. end
  171. if hit
  172. @stream_client.to_group(tweet, @channel.options['sync']['mentions']['group_id'], @channel)
  173. next
  174. end
  175. end
  176. # check hashtags
  177. if @channel.options['sync']['search'] && tweet.hashtags
  178. hit = false
  179. @channel.options['sync']['search'].each {|item|
  180. tweet.hashtags.each {|hashtag|
  181. next if item['term'] !~ /^#/
  182. if item['term'].sub(/^#/, '') == hashtag.text
  183. hit = item
  184. end
  185. }
  186. }
  187. if hit
  188. @stream_client.to_group(tweet, hit['group_id'], @channel)
  189. next
  190. end
  191. end
  192. # check stings
  193. if @channel.options['sync']['search']
  194. hit = false
  195. body = tweet.text
  196. @channel.options['sync']['search'].each {|item|
  197. next if item['term'] =~ /^#/
  198. if body =~ /#{item['term']}/
  199. hit = item
  200. end
  201. }
  202. if hit
  203. @stream_client.to_group(tweet, hit['group_id'], @channel)
  204. end
  205. end
  206. end
  207. end
  208. private
  209. def fetch_search
  210. return if !@sync[:search]
  211. return if @sync[:search].empty?
  212. @sync[:search].each { |search|
  213. result_type = search[:type] || 'mixed'
  214. Rails.logger.debug " - searching for '#{search[:term]}'"
  215. @rest_client.client.search(search[:term], result_type: result_type).collect { |tweet|
  216. next if Ticket::Article.find_by(message_id: tweet.id)
  217. break if @rest_client.tweet_limit_reached(tweet)
  218. @rest_client.to_group(tweet, search[:group_id], @channel)
  219. }
  220. }
  221. end
  222. def fetch_mentions
  223. return if !@sync[:mentions]
  224. return if @sync[:mentions].empty?
  225. Rails.logger.debug ' - searching for mentions'
  226. @rest_client.client.mentions_timeline.each { |tweet|
  227. next if Ticket::Article.find_by(message_id: tweet.id)
  228. break if @rest_client.tweet_limit_reached(tweet)
  229. @rest_client.to_group(tweet, @sync[:mentions][:group_id], @channel)
  230. }
  231. end
  232. def fetch_direct_messages
  233. return if !@sync[:direct_messages]
  234. return if @sync[:direct_messages].empty?
  235. Rails.logger.debug ' - searching for direct_messages'
  236. @rest_client.client.direct_messages.each { |tweet|
  237. next if Ticket::Article.find_by(message_id: tweet.id)
  238. break if @rest_client.direct_message_limit_reached(tweet)
  239. @rest_client.to_group(tweet, @sync[:direct_messages][:group_id], @channel)
  240. }
  241. end
  242. def check_external_credential(options)
  243. if options[:auth] && options[:auth][:external_credential_id]
  244. external_credential = ExternalCredential.find_by(id: options[:auth][:external_credential_id])
  245. fail "No such ExternalCredential.find(#{options[:auth][:external_credential_id]})" if !external_credential
  246. options[:auth][:consumer_key] = external_credential.credentials['consumer_key']
  247. options[:auth][:consumer_secret] = external_credential.credentials['consumer_secret']
  248. end
  249. options
  250. end
  251. end