facebook.rb 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. # Copyright (C) 2012-2015 Zammad Foundation, http://zammad-foundation.org/
  2. require 'koala'
  3. class Facebook
  4. attr_accessor :client, :account
  5. def initialize(options)
  6. connect( options[:auth][:access_token] )
  7. page_access_token = access_token_for_page( options[:sync] )
  8. if page_access_token
  9. connect( page_access_token )
  10. end
  11. @account = client.get_object('me')
  12. end
  13. def connect(access_token)
  14. @client = Koala::Facebook::API.new( access_token )
  15. end
  16. def disconnect
  17. return if !@client
  18. @client = nil
  19. end
  20. def pages
  21. pages = []
  22. @client.get_connections('me', 'accounts').each { |page|
  23. pages.push({
  24. id: page['id'],
  25. name: page['name'],
  26. access_token: page['access_token'],
  27. })
  28. }
  29. pages
  30. end
  31. def user(item)
  32. return if !item['from']
  33. return if !item['from']['id']
  34. return if !item['from']['name']
  35. return if item['from']['id'] == @account['id']
  36. @client.get_object( item['from']['id'] )
  37. end
  38. def to_user(item)
  39. Rails.logger.debug 'Create user from item...'
  40. Rails.logger.debug item.inspect
  41. # do item_user lookup
  42. item_user = user(item)
  43. return if !item_user
  44. auth = Authorization.find_by( uid: item_user['id'], provider: 'facebook' )
  45. # create or update user
  46. user_data = {
  47. login: item_user['id'], # TODO
  48. firstname: item_user['first_name'] || item_user['name'],
  49. lastname: item_user['last_name'] || '',
  50. email: '',
  51. password: '',
  52. # TODO: image_source: '',
  53. # TODO: note: '',
  54. active: true,
  55. roles: Role.where( name: 'Customer' ),
  56. }
  57. if auth
  58. user_data[:id] = auth.user_id
  59. end
  60. user = User.create_or_update( user_data )
  61. # create or update authorization
  62. auth_data = {
  63. uid: item_user['id'],
  64. username: item_user['id'], # TODO
  65. user_id: user.id,
  66. provider: 'facebook'
  67. }
  68. if auth
  69. auth.update_attributes( auth_data )
  70. else
  71. Authorization.new( auth_data )
  72. end
  73. UserInfo.current_user_id = user.id
  74. user
  75. end
  76. def to_ticket(post, group_id)
  77. Rails.logger.debug 'Create ticket from post...'
  78. Rails.logger.debug post.inspect
  79. Rails.logger.debug group_id.inspect
  80. user = to_user(post)
  81. return if !user
  82. Ticket.create(
  83. customer_id: user.id,
  84. title: "#{post['message'][0, 37]}...",
  85. group_id: group_id,
  86. state: Ticket::State.find_by( name: 'new' ),
  87. priority: Ticket::Priority.find_by( name: '2 normal' ),
  88. )
  89. end
  90. def to_article(post, ticket)
  91. Rails.logger.debug 'Create article from post...'
  92. Rails.logger.debug post.inspect
  93. Rails.logger.debug ticket.inspect
  94. # set ticket state to open if not new
  95. if ticket.state.name != 'new'
  96. ticket.state = Ticket::State.find_by( name: 'open' )
  97. ticket.save
  98. end
  99. user = to_user(post)
  100. return if !user
  101. feed_post = {
  102. from: "#{user.firstname} #{user.lastname}",
  103. body: post['message'],
  104. message_id: post['id'],
  105. type_id: Ticket::Article::Type.find_by( name: 'facebook feed post' ).id,
  106. }
  107. articles = []
  108. articles.push( feed_post )
  109. if post['comments'] && post['comments']['data']
  110. articles += nested_comments( post['comments']['data'], post['id'] )
  111. end
  112. articles.each { |article|
  113. next if Ticket::Article.find_by( message_id: article[:message_id] )
  114. article = {
  115. to: @account['name'],
  116. ticket_id: ticket.id,
  117. internal: false,
  118. sender_id: Ticket::Article::Sender.lookup( name: 'Customer' ).id,
  119. created_by_id: 1,
  120. updated_by_id: 1,
  121. }.merge( article )
  122. Ticket::Article.create( article )
  123. }
  124. end
  125. def to_group(post, group_id)
  126. Rails.logger.debug 'import post'
  127. ticket = nil
  128. # use transaction
  129. ActiveRecord::Base.transaction do
  130. UserInfo.current_user_id = 1
  131. existing_article = Ticket::Article.find_by( message_id: post['id'] )
  132. if existing_article
  133. ticket = existing_article.ticket
  134. else
  135. ticket = to_ticket(post, group_id)
  136. return if !ticket
  137. end
  138. to_article(post, ticket)
  139. # execute ticket events
  140. Observer::Ticket::Notification.transaction
  141. end
  142. ticket
  143. end
  144. def from_article(article)
  145. post = nil
  146. if article[:type] == 'facebook feed comment'
  147. Rails.logger.debug 'Create feed comment from article...'
  148. post = @client.put_comment(article[:in_reply_to], article[:body])
  149. else
  150. fail "Can't handle unknown facebook article type '#{article[:type]}'."
  151. end
  152. Rails.logger.debug post.inspect
  153. @client.get_object( post['id'] )
  154. end
  155. private
  156. def access_token_for_page(lookup)
  157. access_token = nil
  158. pages.each { |page|
  159. next if !lookup[:page_id] && !lookup[:page]
  160. next if lookup[:page_id] && lookup[:page_id].to_s != page[:id]
  161. next if lookup[:page] && lookup[:page] != page[:name]
  162. access_token = page[:access_token]
  163. break
  164. }
  165. access_token
  166. end
  167. def nested_comments(comments, in_reply_to)
  168. Rails.logger.debug 'Fetching nested comments...'
  169. Rails.logger.debug comments.inspect
  170. result = []
  171. return result if comments.empty?
  172. comments.each { |comment|
  173. user = to_user(comment)
  174. next if !user
  175. article_data = {
  176. from: "#{user.firstname} #{user.lastname}",
  177. body: comment['message'],
  178. message_id: comment['id'],
  179. type_id: Ticket::Article::Type.find_by( name: 'facebook feed comment' ).id,
  180. in_reply_to: in_reply_to
  181. }
  182. result.push( article_data )
  183. sub_comments = @client.get_object( "#{comment['id']}/comments" )
  184. sub_articles = nested_comments(sub_comments, comment['id'])
  185. result += sub_articles
  186. }
  187. result
  188. end
  189. end