diff src/facebook.coffee @ 0:b73191efc65b

Initial import of pumpbridge (bloody bloody alpha)
author Mathias Gebbe <mgebbe@intevation.de>
date Thu, 05 Jun 2014 10:35:15 +0200
parents
children 98a070c98982
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/facebook.coffee	Thu Jun 05 10:35:15 2014 +0200
@@ -0,0 +1,442 @@
+# Copyright (C) 2014 by Intevation GmbH
+# Author: Mathias Gebbe <mgebbe@intevation.de>
+#
+# This file is Free Software under the Apache License, Version 2.0
+# (the "License"); and comes with ABSOLUTELY NO WARRANTY!
+# You may not use this file except in compliance with the License.
+# See LICENSE for details.
+
+https = require("https")
+async = require("async")
+_ = require("underscore")
+Routes = require("./routes")
+FB = require('fb')
+EdgeControl = require("./edgecontrol")
+Edge = require("./edge")
+CommentToESN = require("./commenttoesn")
+ToESN = require("./toESN")
+FromESN = require("./fromESN")
+Pump = require("./pumpio")
+User = require("./user")
+Sync = require("./sync")
+Usermap = require("./usermap")
+Config = require("./config")
+
+config = Config.config
+
+bridgeid = config.bridgeid
+secret = config.fbSECRET
+appid = config.fbAPPID
+
+#######################################
+###### facebook sync              #####
+#######################################
+
+sync = (user) ->
+  me = user.user_pumpio
+  id = user.user_ESN.substr(0,user.user_ESN.indexOf('@'))
+  pubuser = ""
+  post = ""
+
+  # GET NEW POSTS
+  ####
+  async.waterfall [
+    (callback) ->
+      getFriends(user)
+      getPages(user)
+      getUser(user)
+      getStream user,callback
+  ], (err, posts) ->
+    return if not (posts?)
+    #console.log JSON.stringify(posts) # all posts from network (100)
+    async.eachSeries posts, ((post, callback) ->
+
+      async.waterfall [
+        (callback) ->
+          FromESN.search {uid: post.id + "@facebook_to_" + me, recipientUser: me}, callback
+        (result, callback) ->
+          return if result.length isnt 0 or post.from.id == id
+          #console.log "postid: " + post.from.id + "id:" + id
+          # if this is your own post return!!!
+          getPublicUserInfo(post.from.id , callback)
+        (pubuser, callback) ->
+          pubuser = pubuser
+          User.search {id: pubuser.id + "@facebook"}, callback
+        (dbuser, callback) ->
+          Sync.postParser post, dbuser[0], 'facebook', callback
+        (parsed, callback) ->
+          Pump.postUser bridgeid, me, parsed, callback
+        (pumppost, callback) ->
+          pumppost = JSON.parse(pumppost)
+          FromESN.create
+            postid: post.id + "@facebook"
+            sourceUser: post.from.id
+            sourcePost: post.actions[0].link
+            pumpPost: pumppost.object.id
+            recipientUser: me
+            created: Date.now()
+          , callback
+     ], (err, result) ->
+          #console.log result
+          #console.log 'done.'
+      callback null, 'done'
+    ), (err) ->
+      if err
+        console.log 'one post fail to process'
+      else
+        console.log 'all posts processed'
+      return
+  ####
+  # TO DO: GET NEW COMMENTS
+  # for each fromESN check the comments
+  # if comment author = me
+  # post comment
+  # if comment author != me
+  # post comment with 'user schreibt'
+  async.waterfall [
+    (callback) ->
+      FromESN.search {recipientUser: me}, callback
+    (allESN, callback) ->
+      async.each allESN, ((fromesn, callback) ->
+        async.waterfall [
+          (cb) ->
+            cb (true) if fromesn.sourcePost.indexOf('www.facebook.com') is -1
+            Usermap.search {id: me + '_to_' + me}, cb
+          (pumpuser, cb) ->
+            Pump.getNote(pumpuser[0], fromesn.pumpPost, cb)
+          (note, cb) ->
+            if note.liked is not undefined and note.liked is true
+              obj = fromesn.postid.substr(0,fromesn.postid.indexOf('@'))
+              postLike(user,obj)
+            if (note.replies?)
+              reply = JSON.stringify(note.replies)
+              rep = JSON.parse(reply)
+              if rep.totalItems >= 1
+                async.each rep.items, ((r, callback) ->
+                  if r.author.id is "acct:" + me
+                    obj = fromesn.postid.substr(0,fromesn.postid.indexOf('@'))
+                    postComment(user, obj, r.id , r.content)
+                  callback null, 'done'
+                ), (err) ->
+            cb null, 'done'
+        ], (err, result) ->
+         #done
+      ), (err) ->
+        callback null, 'done'
+  ], (err, result) ->
+    #done
+
+
+  # GET PUBLIC PUMP POSTS AND POST THEM
+  async.waterfall [
+    (callback) ->
+      Usermap.search {id: me + '_to_' + me}, callback
+    (user, callback) ->
+      Pump.getUserFeed(user[0],callback)
+    (feed, callback) ->
+      async.eachSeries feed.items, ((post, callback) ->
+        # do for each post
+        if (post.verb is "post" or post.verb is "share") and (post.object.objectType is "note" or post.object.objectType is "image") and (Pump.isPublicActivity(post)) and (typeof post.object.deleted is "undefined")
+          postStream(user,post)
+        callback null, 'done'
+      ), (err) ->
+        callback null, 'done'
+  ],(err, result) ->
+        #console.log 'done.'
+
+  return
+
+
+#######################################
+###### get user facebook          #####
+#######################################
+getUser = (user) ->
+  data = ""
+  id = user.user_ESN.substr(0,user.user_ESN.indexOf('@'))
+  token = user.oauth_token
+  fields = 'fields=id,name,picture,link'
+  options =
+   host: 'graph.facebook.com'
+   port: 443
+   path: '/' + id + '?access_token=' + token + '&' + fields
+
+  https.get(options, (res) ->
+    #console.log "Got response: " + res.statusCode
+
+    res.on "data", (chunk) ->
+      data += chunk
+      return
+
+    res.on "end", () ->
+      user = JSON.parse(data)
+      ### with app id ###
+      Routes.updateUserDB(user.id+'@facebook',user.name,user.name,user.link,user.picture.data.url) unless typeof user is "undefined"
+      ### with link ###
+      Routes.updateUserDB(user.link,user.name,user.name,user.link,user.picture.data.url) unless typeof user is "undefined"
+      return
+
+  ).on "error", (e) ->
+    console.log "Got error: " + e.message
+
+  return
+
+##############################################
+###### get facebook friends /remove all ######
+##############################################
+getFriends = (user) ->
+  me = user.user_pumpio
+  id = user.user_ESN.substr(0,user.user_ESN.indexOf('@'))
+  token = user.oauth_token
+
+  EdgeControl.removeEdges(me,'@facebook')
+  EdgeControl.removeEdges(me,'www.facebook.com')
+
+  FB.setAccessToken token
+  FB.api "fql",
+    q: "SELECT uid2 FROM friend WHERE uid1 = me()"
+  , (res) ->
+    if not res or res.error
+      console.log (if not res then "error occurred" else res.error)
+      return
+
+    _.each res.data, (user) ->
+      getUserById(me,user.uid2,token) unless typeof user.id is "undefined"
+      return
+
+    return
+
+  return
+
+##############################################
+###### get facebook likes               ######
+##############################################
+getPages = (user) ->
+  me = user.user_pumpio
+  token = user.oauth_token
+
+  FB.setAccessToken token
+
+  FB.api "me/likes?limit=1000&",
+    fields: [
+      "id"
+    ]
+  , (res) ->
+    if not res or res.error
+      console.log (if not res then "error occurred" else res.error)
+
+    _.each res.data, (page) ->
+      getUserById(me,page.id,token) unless typeof user.id is "undefined"
+      return
+
+
+  return
+
+
+#######################################
+###### get facebook stream       ######
+#######################################
+getStream = (user,callback) ->
+  token = user.oauth_token
+
+  FB.setAccessToken token
+
+  FB.api "me/home?limit=25&",
+    fields: [
+      "id"
+      "type"
+      "from"
+      "privacy"
+      "message"
+      "picture"
+      "link"
+      "status_type"
+      "caption"
+      "created_time"
+      "updated_time"
+      "picture"
+      "actions"
+    ]
+  , (res) ->
+    if not res or res.error
+      console.log (if not res then "error occurred" else res.error)
+      callback null, null
+
+    newposts = new Array()
+    _.each res.data, (post) ->
+      newposts.push(post) if (post.type is 'status' or post.type is 'photo' or post.type is 'link' or post.type is 'video') and (post.status_type is 'mobile_status_update' or post.status_type is 'added_photos' or post.status_type is 'shared_story')
+
+    callback null, newposts.reverse()
+
+#######################################
+###### post facebook stream      ######
+#######################################
+postStream = (user, post) ->
+  token = user.oauth_token
+
+  FB.setAccessToken token
+
+  return if typeof post.object.content  is "undefined" or post.object.content is ""
+  ToESN.search {uid: post.object.id }, (err, result) ->
+    if result.length is 0
+      body = post.object.content.replace(/<(?:.|\n)*?>/gm, '') + " " + post.object.url
+
+      FB.api "me/feed", "post",
+        message: body
+      , (res) ->
+        if not res or res.error
+          console.log (if not res then "error occurred" else res.error)
+          return
+
+        async.waterfall [
+          (callback) ->
+            savePost = new ToESN()
+            savePost.uid = post.object.id
+            savePost.sourceUser = post.actor.id
+            savePost.sourcePost = post.object.id
+            savePost.targetUser = user.user_ESN
+            savePost.targetPost = res.id
+            savePost.recipientUser = 'public'
+            savePost.updated = Date.now()
+            savePost.save callback
+        ], (err, result) ->
+
+        return
+
+  return
+
+##################################################
+###### post comment to facebook stream      ######
+##################################################
+postComment = (user, object_id, pumpid, text) ->
+
+# check if the comment is allready posted (search bla return)
+
+  CommentToESN.search { uid: pumpid + "_to_" + "https://facebook.com/" + object_id}, (err, result) ->
+    if result.length is 0
+      token = user.oauth_token
+      text = text.replace /<(?:.|\n)*?>/g, ""
+
+      FB.setAccessToken token
+
+      FB.api "" + object_id + "/comments", "POST",
+        message: text
+      , (res) ->
+        if not res or res.error
+          console.log (if not res then "error occurred" else res.error)
+          return
+
+      CommentToESN.create
+        ESNPost: "https://facebook.com/" + object_id
+        pumpComment: pumpid
+        created: Date.now()
+      , (err, result) ->
+        console.log 'comment saved'
+
+  return
+
+##################################################
+###### like post on facebook stream         ######
+##################################################
+postLike = (user, object_id) ->
+  token = user.oauth_token
+  FB.setAccessToken token
+
+  FB.api "" + object_id + "/likes", "POST"
+  , (res) ->
+    if not res or res.error
+      console.log (if not res then "error occurred" else res.error)
+      return
+
+    console.log 'liked'
+    return
+
+  return
+
+
+######################################################################
+###### get user facebook by id and add him to UserDB and EDGES   #####
+######################################################################
+getUserById = (me,id,token) ->
+  data = ""
+  token = token
+  fields = 'fields=id,name,picture,link'
+  options =
+   host: 'graph.facebook.com'
+   port: 443
+   path: '/' + id + '?access_token=' + token + '&' + fields
+
+  https.get(options, (res) ->
+    #console.log "Got response: " + res.statusCode
+
+    res.on "data", (chunk) ->
+      data += chunk
+      return
+
+    res.on "end", () ->
+      user = JSON.parse(data) unless data isnt "undefined"
+
+      #### with app user id ###
+      Routes.updateUserDB(user.id+'@facebook',user.name,user.name,user.link,user.picture.data.url) unless typeof user is "undefined"
+      EdgeControl.addEdge(me,user.id+'@facebook') unless typeof user is "undefined"
+
+      #### with profile url ###
+      Routes.updateUserDB(user.link,user.name,user.name,user.link,user.picture.data.url) unless typeof user is "undefined"
+      EdgeControl.addEdge(me,user.link) unless typeof user is "undefined"
+
+
+      return
+
+  ).on "error", (e) ->
+    console.log "Got error: " + e.message
+
+  return
+
+
+######################################################################
+###### get user facebook by id and add him to UserDB and EDGES   #####
+######################################################################
+getPublicUserInfo = (id, callback) ->
+
+  FB.api ""+id,
+   (res) ->
+     if not res or res.error
+       console.log (if not res then "error occurred" else res.error)
+     callback null,res
+
+  return
+
+######################################################################
+###### get facebook long lived token                             #####
+######################################################################
+getLongLivedToken = (token, callback) ->
+  data = ""
+  options =
+   host: 'graph.facebook.com'
+   port: 443
+   path: '/oauth/access_token?' + 'grant_type=fb_exchange_token&client_id='+ appid + '&client_secret=' + secret + '&fb_exchange_token=' + token + ''
+
+  https.get(options, (res) ->
+    res.on "data", (chunk) ->
+      data += chunk
+      return
+
+    res.on "end", () ->
+      # returns --> "access_token=CAAK9efmXh2IBAAm9abitB98TvF6HHF5ducYDkV5PBrooG6MVNoP9eOy06yvyL0hMKQVzh1xvJPM8XMAYe8L0ZARzZCdolahSymrZCDXN2ZAfr0aIFbWocr8K5DMLu64ZD&expires=5183792"
+      ltoken = JSON.stringify(data)
+      callback ltoken.substring(ltoken.indexOf('=')+1,ltoken.indexOf('&'))
+      return
+
+  ).on "error", (e) ->
+    console.log "Got error: " + e.message
+
+  return
+
+exports.getUser = getUser
+exports.getPages = getPages
+exports.getStream = getStream
+exports.getFriends = getFriends
+exports.postStream = postStream
+exports.getLongLivedToken = getLongLivedToken
+exports.getPublicUserInfo = getPublicUserInfo
+exports.getUserById = getUserById
+exports.sync = sync
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)